<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"chuangges.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="HTML CSS、JS、JS 框架、小程序、编程相关">
<meta property="og:type" content="article">
<meta property="og:title" content="面试题之基础篇">
<meta property="og:url" content="https://chuangges.gitee.io/2020/03/22/12-%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B9%8B%E5%9F%BA%E7%A1%80%E7%AF%87/index.html">
<meta property="og:site_name" content="闯哥要去流浪了">
<meta property="og:description" content="HTML CSS、JS、JS 框架、小程序、编程相关">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2020-03-22T09:31:06.000Z">
<meta property="article:modified_time" content="2023-11-02T02:00:38.972Z">
<meta property="article:author" content="chuangges">
<meta property="article:tag" content="面试题库">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="https://chuangges.gitee.io/2020/03/22/12-%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B9%8B%E5%9F%BA%E7%A1%80%E7%AF%87/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>面试题之基础篇 | 闯哥要去流浪了</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="闯哥要去流浪了" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">闯哥要去流浪了</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">愿你岁月可回首，且以深情共白头</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://chuangges.gitee.io/2020/03/22/12-%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B9%8B%E5%9F%BA%E7%A1%80%E7%AF%87/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/chuang.png">
      <meta itemprop="name" content="chuangges">
      <meta itemprop="description" content="chuangge's blog.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="闯哥要去流浪了">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          面试题之基础篇
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-22 17:31:06" itemprop="dateCreated datePublished" datetime="2020-03-22T17:31:06+08:00">2020-03-22</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-11-02 10:00:38" itemprop="dateModified" datetime="2023-11-02T10:00:38+08:00">2023-11-02</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E9%9D%A2%E8%AF%95%E9%A2%98%E5%BA%93/" itemprop="url" rel="index"><span itemprop="name">面试题库</span></a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>37k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>33 分钟</span>
            </span>
            <div class="post-description">HTML CSS、JS、JS 框架、小程序、编程相关</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="一、HTML、CSS"><a href="#一、HTML、CSS" class="headerlink" title="一、HTML、CSS"></a>一、HTML、CSS</h1><ul>
<li><strong>语义化理解</strong>：使用合理标签来创建页面内容，让页面结构更清晰。好处是便于浏览器和搜索引擎解析，提高代码的可读性和重用性。</li>
<li><strong>CSS 盒模型</strong>：width&#x2F;height 设置的宽高只是指 content、盒子宽高 &#x3D;&#x3D; 内容 + 填充 + 边距 + 边框、标准盒模型 box-sizing: content-box、IE 盒模型 box-sizing: border-box。</li>
<li><strong>图片加载优化</strong>：可视区域的图片懒加载 (按需加载)、前后图片的预加载 (页面加载完成之前下载所需资源，使用时从缓存中调用) 、使用雪碧图。</li>
<li><strong>WebP</strong>：谷歌开发的一种支持有损压缩和无损压缩的新图片格式，优点是相同质量的图片拥有更小的文件体积，非常适合于网络图片的传输。</li>
<li><strong>header token 为何不会被劫持</strong>：token 不是防止 XSS 而是为了防止 CSRF、CSRF 攻击的原因是浏览器会自动带上 cookie 而浏览器不会自动带上 token。</li>
<li><strong>宽高覆盖规则</strong>：min-width &gt; max-width &gt; width，即使设置了行内样式或 !important。</li>
<li><strong>性能指标</strong>：FP 首次绘制、FCP 首次内容绘制、LCP 最大内容绘制时间、FPS 每秒传输帧数、TTI 页面可交互时间、HTTP 请求响应时间、DNS 解析时间、TCP 连接时间</li>
</ul>
<h2 id="link、-import-导入"><a href="#link、-import-导入" class="headerlink" title="link、@import 导入"></a>link、@import 导入</h2><ul>
<li><strong>从属关系</strong>：@import 只能用于加载 CSS，link 是 XHTML 标签，它还可以定义 RSS、rel 连接属性、引入网站图标等。</li>
<li><strong>加载顺序</strong>：加载页面时，link 引入的 CSS 被同时加载，@import 引入的 CSS 会等到页面被全部加载完成后再加载。</li>
<li><strong>兼容性</strong>：link 无兼容性问题，@import 只有 IE5+ 才能被识别。</li>
</ul>
<h2 id="HTML5-form-自动完成"><a href="#HTML5-form-自动完成" class="headerlink" title="HTML5 form 自动完成"></a>HTML5 form 自动完成</h2><ul>
<li><strong>autocomplete</strong> 属性规定表单是否应该启用自动完成功能，它自动完成允许浏览器预测对输入字段。在用户在开始键入时，浏览器基于之前键入过的值显示出历史选项。</li>
<li>关闭自动完成功能的方法：IE Internet 选项菜单的内容–自动完成设置、form autocomplete&#x3D;”off” 关闭整个表单的自动提示功能、input autocomplete&#x3D;”off” 关闭输入框的自动完成功能。</li>
</ul>
<h2 id="浏览器渲染"><a href="#浏览器渲染" class="headerlink" title="浏览器渲染"></a>浏览器渲染</h2><blockquote>
<p>渲染引擎为了更好的用户体验会尽快将内容呈现到屏幕，它是解析完一部分内容就会显示而不会等到所有内容解析完成之后再去构建 render tree。</p>
</blockquote>
<ol>
<li>解析 HTML 标记并构建 <strong>DOM 树</strong>。</li>
<li>解析 CSS 标记并构建 <strong>CSSOM 树</strong>。</li>
<li>根据 DOM、CSSOM 构建<strong>渲染树</strong>，节点是包含颜色等属性的渲染对象。</li>
<li><strong>布局</strong>：根据渲染树进行布局，计算各个节点在页面的位置、大小等信息。</li>
<li><strong>绘制</strong>：调用渲染对象的 paint 方法，将它们的内容显示在屏幕并绘制基础组件。</li>
</ol>
<h2 id="浏览器通信"><a href="#浏览器通信" class="headerlink" title="浏览器通信"></a>浏览器通信</h2><blockquote>
<p>由于标签页之间无法直接通信，它们的通信本质都是通过中介者转发消息来实现的。</p>
</blockquote>
<ol>
<li><strong>Websocket</strong>：通信的标签页连接同一个服务器，服务器将收到的消息推送给所有客户端。</li>
<li><strong>localStorage</strong>：localStorage 在浏览上下文中新增&#x2F;修改&#x2F;删除时会触发 storage 事件。</li>
<li><strong>SharedWorker</strong>：服务器注册一个 onmessage 监听信息的事件，客户端(即使用 sharedWorker 的标签页)发送 message 时就会触发。</li>
</ol>
<h2 id="浏览器缓存"><a href="#浏览器缓存" class="headerlink" title="浏览器缓存"></a>浏览器缓存</h2><ul>
<li>缓存类型：根据响应头内容分为强制缓存和协商缓存，优先级顺序依次为 <strong>cache-control、Expires、Etag、Last-modified</strong>。</li>
<li>缓存位置：<strong>Service Worker</strong> (运行在浏览器背后的独立线程)、<strong>Memory Cache</strong> (包含页面资源的内存缓存，关闭页面则释放)、<strong>Disk Cache</strong> (存储在硬盘)、<strong>Push Cache</strong> (会话缓存)。</li>
<li>缓存过程：浏览器在缓存中查找请求结果和缓存标识后发起请求，将返回结果存入缓存并根据响应头内容进行相应处理。</li>
</ul>
<h2 id="CSRF-攻击"><a href="#CSRF-攻击" class="headerlink" title="CSRF 攻击"></a>CSRF 攻击</h2><ul>
<li><strong>实现</strong>：跨站请求伪造攻击，攻击者诱导用户进入一个第三方网站，然后该网站向被攻击网站发送跨站请求。如果用户在被攻击网站中保存了登录状态，那么攻击者就可以利用这个登录状态（cookie），绕过后台的用户验证，冒充用户向服务器执行一些操作。</li>
<li><strong>本质</strong>：利用 cookie 会在同源请求中携带发送给服务器的特点来实现冒充用户。</li>
<li><strong>防护方法</strong>：同源检测和服务器检测请求来源、使用 token 验证、设置 cookie 时设置 Samesite 并限制为不能作为被第三方使用。</li>
</ul>
<h2 id="CSP-内容安全策略"><a href="#CSP-内容安全策略" class="headerlink" title="CSP 内容安全策略"></a>CSP 内容安全策略</h2><ul>
<li><strong>实现</strong>：本质是建立一个白名单，告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则，如何拦截由浏览器自己来实现。它也是解决 XSS 攻击的一个强力手段。</li>
<li><strong>开启</strong>：一种是设置 <code>HTTP 头部 Content-Security-Policy</code>，一种是设置 <code>meta 标签 &lt;meta http-equiv=&quot;Content-Security-Policy&quot;&gt;</code>。</li>
</ul>
<h2 id="PWA-渐进式网页应用"><a href="#PWA-渐进式网页应用" class="headerlink" title="PWA 渐进式网页应用"></a>PWA 渐进式网页应用</h2><blockquote>
<p>Progressive Web App 是一个让普通站点过渡到 Web 应用的渐进式过渡方案。目的是降低站点改造代价并逐渐支持新技术，从而提升性能和改善用户体验。</p>
</blockquote>
<ul>
<li>可安装：可以像原生 APP 在主屏幕上留有图标。</li>
<li>支持离线存储和消息推送：运行在浏览器进程的 ServiceWorker 能够为所有页面提供服务。</li>
<li>ServiceWorker：本质是一段在后台运行的脚本。作为一个运行环境不同于普通脚本的独立线程，不能直接参与 Web 交互行为，属于一种客户端代理。</li>
</ul>
<h2 id="HTTPS-让数据传输更安全"><a href="#HTTPS-让数据传输更安全" class="headerlink" title="HTTPS 让数据传输更安全"></a>HTTPS 让数据传输更安全</h2><ul>
<li>TCP、HTTP 之间插入一个安全层，所有经过安全层的数据都会被加密或解密。</li>
<li>对称加密：浏览器发送加密套件列表和一个随机数，服务器从列表选取一个加密套件并生成一个随机数返回，然后通过相同方法将两个随机数混合生成一个密钥后进行数据加密。缺点是随机数的过程都是明文，黑客可以拿到协商的加密套件和随机数，生成密钥并破解数据。</li>
<li>非对称加密：浏览器发送加密套件列表，服务器选择一个加密套件返回加密套件和公钥，浏览器用公钥加密数据，服务器用私钥解密。缺点是加密效率太低，不能保证服务器发送给浏览器的数据安全，黑客可以获取公钥。</li>
<li>对称加密结合非对称加密：浏览器发送对称加密套件列表、非对称加密列表和随机数，服务器生成随机数并选择加密套件和公钥返回，浏览器通过随机数计算出 pre-master 并利用公钥给 pre-master 加密后发送，服务器用私钥解密出 pre-master 数据并结合随机数生成对称密钥，使用对称密钥传输加密数据。</li>
<li>数字证书：用于向浏览器证明服务器的身份或用于服务器公钥。CA 使用 Hash 函数技术明文信息得出信息摘要，然后 CA 使用私钥对信息摘要加密后的秘文就是数字签名。验证是否合法时，读取证书明文信息并将相同 Hash 函数计算得到的信息摘要 A 和 CA 公钥解密得到的 B 进行对比，一致则确认证书合法。</li>
</ul>
<h2 id="沙盒隔离页面和系统"><a href="#沙盒隔离页面和系统" class="headerlink" title="沙盒隔离页面和系统"></a>沙盒隔离页面和系统</h2><ul>
<li>浏览器被划分为浏览器内核和渲染内核两个核心模块，其中浏览器内核由网络进程、浏览器主进程和 GPU 进程组成的，渲染内核就是渲染进程。</li>
<li>浏览器中的安全沙箱是利用操作系统提供的安全技术，让渲染进程在执行过程中无法访问或者修改操作系统中的数据，在渲染进程需要访问系统资源时需要通过浏览器内核来实现，然后将访问的结果通过 IPC 转发给渲染进程。</li>
<li>站点隔离（Site Isolation）将同一站点（包含相同根域名和相同协议的地址）中相互关联的页面放到同一个渲染进程中执行，这样就可以将恶意的 iframe 隔离在恶意进程内部而无法继续访问其他 iframe 进程的内容，因此无法攻击其他站点。</li>
</ul>
<h2 id="移动端适配方案"><a href="#移动端适配方案" class="headerlink" title="移动端适配方案"></a>移动端适配方案</h2><ul>
<li><strong>viewport 缩放</strong>：针对不同分辨率的手机设置等比例缩放，但是 PC 端可能会界面变形。</li>
<li><strong>响应式布局</strong>：通过媒体查询根据不同分辨率适配，但代码可维护性差，适用于简单页面。</li>
<li><strong>弹性布局</strong>：使容器子元素的宽高能够合理填充空间，可通过百分比、vw + vh、rem。</li>
<li><strong>vue 方案</strong>：通过 vw 实现适配，安装插件 postcss-px-to-viewport 并配置即可。</li>
</ul>
<h2 id="BFC-及其应用"><a href="#BFC-及其应用" class="headerlink" title="BFC 及其应用"></a>BFC 及其应用</h2><ul>
<li><strong>简单介绍</strong>：Block Format Context 块级格式化上下文，是页面盒模型的一种 CSS 渲染模式，相当于一个独立容器，里面的元素和外部的元素相互不影响。</li>
<li><strong>创建方式</strong>：html 根元素、float、position: absolute&#x2F;fixed、overflow: !visible、display: inline-block&#x2F;table&#x2F;flex。</li>
<li><strong>主要作用</strong>：清除浮动、不同 BFC 时可以阻止 margin 重叠。</li>
</ul>
<h2 id="重绘、回流"><a href="#重绘、回流" class="headerlink" title="重绘、回流"></a>重绘、回流</h2><ul>
<li><strong>重绘重排</strong><ul>
<li>重绘：简单外观的改变而不会影响布局，比如 outline、visibility、color。</li>
<li>回流：布局或几何属性改变而重新计算布局，大部分都会会导致页面的重新渲染。</li>
<li>关系：重绘不一定会引发回流，回流必定会发生重绘，它们都会重新生成渲染树。</li>
</ul>
</li>
<li><strong>优化方案</strong><ul>
<li><strong>JS</strong>：避免频繁操作 DOM、缓存频繁读取的属性值、对复杂动画的元素使用定位。</li>
<li><strong>CSS</strong>：CSS 硬件加速、尽量在 DOM 树的最末端改变 class、避免使用 CSS 表达式而导致回流、避免设置多层内联样式而提高 CSS 选择符从右往左匹配查找速度、将动画效果应用到定位元素而避免影响其他布局。</li>
</ul>
</li>
</ul>
<h2 id="Web-性能优化"><a href="#Web-性能优化" class="headerlink" title="Web 性能优化"></a>Web 性能优化</h2><ul>
<li><strong>减少请求量</strong>：合并资源、减少 HTTP 请求、gzip 压缩、WebP 图片、路由懒加载。</li>
<li><strong>加快请求速度</strong>：预解析 DNS、减少域名数、并行加载、CDN 分发。 </li>
<li><strong>资源预加载</strong>：支持预拉取图片、脚本以及任何可以被浏览器缓存的资源。</li>
<li><strong>渲染优化</strong>：静态渲染 SR、前端渲染 CSR、服务端渲染 SSR、客户端渲染 NSR。</li>
<li><strong>特效优化</strong>：合理利用 CSS 合成动画而避免重绘、将动画效果应用到定位元素。</li>
</ul>
<h2 id="opacity、visibility、display"><a href="#opacity、visibility、display" class="headerlink" title="opacity、visibility、display"></a>opacity、visibility、display</h2><ul>
<li><strong>opacity: 0</strong>：占据空间，可以点击，引起重绘，子元素不影响。</li>
<li><strong>display: none</strong>：不占空间，不能点击，会引起回流，子元素不影响。</li>
<li><strong>visibility: hidden</strong>：占据空间，不能点击，引起重绘，子元素可设置 visible 进行显示。</li>
</ul>
<h2 id="Rem-及其原理"><a href="#Rem-及其原理" class="headerlink" title="Rem 及其原理"></a>Rem 及其原理</h2><ul>
<li><strong>Rem</strong>：CSS3 新增的相对长度单位，指相对于根元素 html 的 font-size 大小，移动端新型浏览器支持较好。px 是相对固定单位，无法随着浏览器进行缩放。</li>
<li><strong>转换原理</strong>：默认根元素的 font-size: 16px，如果想要设置为 12px 则就是 12px&#x2F;16px &#x3D; 0.75rem。通过 postcss-px-to-viewport 插件可以实现对 px 到 vw 的自动转换。</li>
</ul>
<h2 id="移动端视口配置"><a href="#移动端视口配置" class="headerlink" title="移动端视口配置"></a>移动端视口配置</h2><ul>
<li><strong>initial-scale</strong>: 初始的缩放比例。</li>
<li><strong>minimum-scale</strong>: 允许用户缩放到的最小比例。</li>
<li><strong>maximum-scale</strong>: 允许用户缩放到的最大比例。</li>
<li><strong>user-scalable</strong>: 用户是否可以手动缩放。</li>
</ul>
<h2 id="伪类和伪元素"><a href="#伪类和伪元素" class="headerlink" title="伪类和伪元素"></a>伪类和伪元素</h2><ul>
<li><strong>伪类</strong>：用于为处于某种状态的已有元素添加样式，该状态是随着用户行为变化的。比如说 :hover。它只有处于 dom 树无法描述的状态才能为元素添加样式，所以称为伪类。</li>
<li><strong>伪元素</strong>：用于创建一些原本不在文档树中的元素，并为其添加样式。比如 ::before，虽然用户可以看到这些内容，但是其实它不在文档树中。</li>
<li><strong>区别</strong>：伪类的操作对象是文档树中已存在的元素，而伪元素是创建一个文档树外的元素。css 规范规定使用双冒号 :: 表示伪元素，一个冒号 : 表示伪类。</li>
</ul>
<h2 id="css-可继承属性"><a href="#css-可继承属性" class="headerlink" title="css 可继承属性"></a>css 可继承属性</h2><ul>
<li><strong>字体系列属性</strong>：font-family、font-size、font-weight、font-style。</li>
<li><strong>文本系列属性</strong>：text-indent、text-align、line-hight、word-spacing、color。</li>
<li><strong>其他</strong>：cursor、visibility。</li>
</ul>
<h1 id="二、JS"><a href="#二、JS" class="headerlink" title="二、JS"></a>二、JS</h1><ul>
<li><strong>JS 特性</strong>：运行在客户端浏览器、不用预编译而直接解析执行代码、弱类型语言而较为灵活、跨平台的语言而与操作系统无关、脚本语言、解释性语言。</li>
<li><strong>变量提升</strong>：JS 代码执行前需要先编译，在编译阶段将变量设为 undefined 并和函数存到变量环境 (重复则被覆盖)，JS 引擎会在代码执行阶段从变量环境中查找自定义的变量和函数。</li>
<li><strong>变量执行</strong>：JS 引擎使用变量时会在当前的执行上下文中查找变量，没有找到则会继续在作用域链指向的执行上下文中查找。函数总是可以访问其外部函数中声明的变量，当在函数内调用一个外部函数时引用的变量会一直保存在内存，这些变量的集合称为闭包。</li>
<li><strong>闭包</strong>：指能够读取其他函数内部变量的函数，用来实现私有的方法和变量。主要特点有：函数嵌套函数、函数内部引用外部的参数和变量、参数和变量不会被垃圾回收机制回收。优点是可以避免全局变量的污染，缺点是闭包会常驻内存而容易造成内存泄漏。</li>
<li><strong>块级作用域</strong>：let&#x2F;const 变量不会被提升而是在编译后保存到词法环境的一个单独栈区域，作用域内部变量压入栈顶并在作用域执行完后从栈顶弹出。</li>
<li><strong>new 操作符</strong>：新建一个原型 <code>__proto__</code> 指向构造函数 prototype 的空对象，然后将这个新对象赋值给构造函数 this 指向并在执行构造函数后返回。</li>
<li><strong>自执行函数</strong>：声明并立刻调用的匿名函数，用来创建一个独立的作用域，一般用于框架、插件等场景。好处如下：防止变量扩散到全局而造成冲突、隔离作用域避免闭包造成引用变量无法释放、利用立即执行特性返回需要的函数或对象而避免每次通过条件判断处理。</li>
<li><strong>尾调用优化</strong>：指函数的最后一步调用另一个函数。代码执行是基于执行栈的，所以在一个函数里调用另一个函数时，会保留当前的执行上下文并新建另外一个加入栈中。使用尾调用时则不必再保留当前的执行上下文，从而节省了内存，这就是尾调用优化。ES6 的尾调用优化只在严格模式下开启，正常模式是无效的。</li>
<li><strong>Babel 实现 ES6 转为 ES5</strong>：将代码字符串解析成抽象语法树 ES6 AST、处理后转换为 ES5 AST、通过新语法树生成代码字符串。</li>
<li><strong>事件委托</strong>：将原本需要绑定在子元素的监听事件委托给父元素，通过 DOM 元素的事件冒泡机制实现父元素监听到子元素上事件的触发，特别适用于动态元素的绑定。</li>
<li><strong>事件冒泡</strong>：一个事件触发后会在子元素和父元素之间分为三个阶段传播：捕获阶段(window 对象传导到目标节点，不响应任何事件)、目标阶段(在目标节点上触发)，冒泡阶段(从目标节点传导回 window 对象)。</li>
<li><strong>面向对象思想</strong>：将问题分解并抽象为一个个具体对象，并且将对象及其公共的属性和方法封装成一个类，整个程序由对象之间的分工和合作完成。主要特点有封装 (通过对象相互访问)、继承 (从已有对象上继承出新对象)、多态 (多对象的不同形态)，极大提高了程序的复用性性和可维护性。核心在于类的实现：js 基于 function 模拟类，通过 prototype 属性实现类方法的共享，ES6 class 是定义类的一个语法糖，通过 extends 继承父类。</li>
</ul>
<h2 id="JS-编译"><a href="#JS-编译" class="headerlink" title="JS 编译"></a>JS 编译</h2><ul>
<li><strong>两种计算机语言</strong>：编译型语言经过编译器编译后保留机器能读懂的二进制文件，比如 C&#x2F;C++、go。解释型语言是在程序运行时通过解释器对程序进行动态解释和执行，比如 Python、JavaScript。</li>
<li><strong>编译过程</strong>：编译型语言编译器首先将代码进行词法分析和语法分析并生成抽象语法树 AST，编译型语言和最后会被分别处理为机器码和字节码。</li>
<li><strong>字节码</strong>：直接将 AST 转化为机器码时执行效率是非常高但是会消耗大量内存，可以通过转化为字节码解决内存问题，字节码配合解释器和编译器的计数实现称为即时编译 JIT。</li>
</ul>
<h2 id="类型判断"><a href="#类型判断" class="headerlink" title="类型判断"></a>类型判断</h2><ul>
<li><strong>typeof</strong>：判断所有的基本数据类型，返回一个字符串。</li>
<li><strong>instanceOf</strong>：判断一个对象是否某构造函数的实例，返回值为 true&#x2F;false。</li>
<li><strong>constructor</strong>：返回一个对象具体的构造函数，比如 Array、Function、Map。</li>
<li>**Object.prototype.toString.call()**：对象的一个原型扩展函数，可以判断所有数据类型。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typeof</span> <span class="string">&#x27;a&#x27;</span> <span class="number">1</span> <span class="literal">true</span> <span class="title class_">Symbol</span>() <span class="literal">undefined</span> <span class="literal">null</span>  <span class="comment">// 原始类型</span></span><br><span class="line"><span class="keyword">typeof</span> &#123;&#125; [] <span class="keyword">new</span> <span class="title class_">Map</span>/<span class="title class_">Set</span>()                 <span class="comment">// &#x27;object&#x27;</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="keyword">function</span> (<span class="params"></span>) &#123;&#125;;                     <span class="comment">// &#x27;function&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Apple</span> () &#123;&#125;</span><br><span class="line"><span class="keyword">let</span> fun = <span class="keyword">new</span> <span class="title class_">Function</span>();</span><br><span class="line"><span class="keyword">let</span> apple = <span class="keyword">new</span> <span class="title class_">Apple</span>();</span><br><span class="line"></span><br><span class="line">fun <span class="keyword">instanceof</span> <span class="title class_">Function</span>;           <span class="comment">// true</span></span><br><span class="line">apple <span class="keyword">instanceof</span> <span class="title class_">Apple</span>;            <span class="comment">// true</span></span><br><span class="line">apple <span class="keyword">instanceof</span> <span class="title class_">Function</span>;         <span class="comment">// false</span></span><br><span class="line">[] <span class="keyword">instanceof</span> <span class="title class_">Array</span>;               <span class="comment">// true</span></span><br><span class="line">[] <span class="keyword">instanceof</span> <span class="title class_">Object</span>;              <span class="comment">// true</span></span><br><span class="line">&#123;&#125; <span class="keyword">instanceof</span> <span class="title class_">Object</span>               <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">&#123;&#125;.<span class="property">constructor</span> === <span class="title class_">Object</span>;         <span class="comment">// true</span></span><br><span class="line">fun.<span class="property">constructor</span> === <span class="title class_">Function</span>;      <span class="comment">// true</span></span><br><span class="line">apple.<span class="property">constructor</span> === <span class="title class_">Apple</span>;       <span class="comment">// true</span></span><br><span class="line">apple.<span class="property">constructor</span> === <span class="title class_">Function</span>;    <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line">[].<span class="property">constructor</span> === <span class="title class_">Array</span>;          <span class="comment">// true</span></span><br><span class="line">[].<span class="property">constructor</span> === <span class="title class_">Object</span>;         <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Map</span>() <span class="keyword">instanceof</span> <span class="title class_">Map</span>;          <span class="comment">// true</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Map</span>() <span class="keyword">instanceof</span> <span class="title class_">Object</span>        <span class="comment">// true</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Map</span>().<span class="property">constructor</span> === <span class="title class_">Map</span>;     <span class="comment">// true</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Map</span>().<span class="property">constructor</span> === <span class="title class_">Object</span>;  <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">(<span class="keyword">async</span> <span class="keyword">function</span>(<span class="params"></span>)&#123;&#125;)().<span class="property">constructor</span> === <span class="title class_">Promise</span>  <span class="comment">// true</span></span><br><span class="line"><span class="variable language_">this</span>.<span class="property">constructor</span>.<span class="property">constructor</span> === <span class="title class_">Function</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">constructor</span>.<span class="property">constructor</span> === <span class="title class_">Function</span>     <span class="comment">// 浏览器环境 true</span></span><br><span class="line"><span class="variable language_">global</span>.<span class="property">constructor</span>.<span class="property">constructor</span> === <span class="title class_">Function</span>     <span class="comment">// node 环境 true</span></span><br><span class="line"></span><br><span class="line"><span class="title class_">Object</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">toString</span>.<span class="title function_">call</span>(fun);        <span class="comment">// &quot;[object Function]&quot;</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">toString</span>.<span class="title function_">call</span>(apple);      <span class="comment">// &quot;[object Object]&quot;</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">toString</span>.<span class="title function_">call</span>([]);         <span class="comment">// &quot;[object Array]&quot;</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">toString</span>.<span class="title function_">call</span>(<span class="keyword">new</span> <span class="title class_">Map</span>());  <span class="comment">// &quot;[object Map]&quot;</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">toString</span>.<span class="title function_">call</span>(&#123;&#125;);         <span class="comment">// &quot;[object Object]&quot;</span></span><br></pre></td></tr></table></figure>


<h2 id="隐式转换"><a href="#隐式转换" class="headerlink" title="隐式转换"></a>隐式转换</h2><ul>
<li><strong>运算符转换</strong>：-、*、&#x2F;、% 会转换为数字后计算，+ 则进行数字相加或字符串拼接。</li>
<li><strong>双等号转换</strong>：两边会转换为同一类型再进行比较，有一个 NaN 则返回 false。</li>
<li><strong>点号操作符</strong>：数字、字符串等通过点调用方法时，隐式地将类型转换成对象。</li>
<li><strong>if() 语句</strong>：括号里的表达式部分会被隐式转换为布尔类型进行判断。</li>
</ul>
<h2 id="精度丢失"><a href="#精度丢失" class="headerlink" title="精度丢失"></a>精度丢失</h2><blockquote>
<p>计算机存储小数的类型 float&#x2F;double 都是有位数限制的，所以存储的只是一个近似值。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span>：round</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> Precision：精度</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> RoundValue：舍入值 (数字)，</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> RoundType：舍入类型 (1 全部进位、2 全部舍位、3 按值舍入)</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">formatNumber</span> = <span class="keyword">function</span>(<span class="params">val, round</span>) &#123;</span><br><span class="line">  <span class="keyword">if</span> (val == <span class="literal">undefined</span> || val == <span class="literal">null</span> || val.<span class="title function_">toString</span>().<span class="title function_">trim</span>() == <span class="string">&#x27;&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (<span class="title class_">Object</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">toString</span>.<span class="title function_">call</span>(round) != <span class="string">&#x27;[object Object]&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> val;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">var</span> returnValue;</span><br><span class="line">  round.<span class="property">Precision</span> = round.<span class="property">Precision</span> || <span class="number">0</span>;</span><br><span class="line">  round.<span class="property">RoundType</span> = round.<span class="property">RoundType</span> || <span class="number">3</span>;</span><br><span class="line">  round.<span class="property">RoundValue</span> = round.<span class="property">RoundValue</span> || <span class="number">5</span>;</span><br><span class="line">  <span class="keyword">if</span> (round.<span class="property">RoundType</span> == <span class="number">1</span>) &#123;</span><br><span class="line">      returnValue = <span class="title class_">Math</span>.<span class="title function_">ceil</span>(val * <span class="title class_">Math</span>.<span class="title function_">pow</span>(<span class="number">10</span>, round.<span class="property">Precision</span> + <span class="number">1</span>));</span><br><span class="line">      <span class="keyword">if</span> (returnValue % <span class="number">10</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">          returnValue = <span class="built_in">parseInt</span>(val * <span class="title class_">Math</span>.<span class="title function_">pow</span>(<span class="number">10</span>, round.<span class="property">Precision</span>)) + <span class="number">1</span>;</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          returnValue = <span class="built_in">parseInt</span>(val * <span class="title class_">Math</span>.<span class="title function_">pow</span>(<span class="number">10</span>, round.<span class="property">Precision</span>));</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> (round.<span class="property">RoundType</span> == <span class="number">2</span>) &#123;</span><br><span class="line">      returnValue = <span class="built_in">parseInt</span>(val * <span class="title class_">Math</span>.<span class="title function_">pow</span>(<span class="number">10</span>, round.<span class="property">Precision</span>))</span><br><span class="line">  </span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      returnValue = <span class="title class_">Math</span>.<span class="title function_">ceil</span>(val * <span class="title class_">Math</span>.<span class="title function_">pow</span>(<span class="number">10</span>, round.<span class="property">Precision</span> + <span class="number">1</span>));</span><br><span class="line">      <span class="keyword">if</span> (returnValue % <span class="number">10</span> &gt;= round.<span class="property">RoundValue</span>) &#123;</span><br><span class="line">          returnValue = <span class="built_in">parseInt</span>(val * <span class="title class_">Math</span>.<span class="title function_">pow</span>(<span class="number">10</span>, round.<span class="property">Precision</span>)) + <span class="number">1</span>;</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          returnValue = <span class="built_in">parseInt</span>(returnValue / <span class="number">10</span>);</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  returnValue = returnValue / <span class="title class_">Math</span>.<span class="title function_">pow</span>(<span class="number">10</span>, round.<span class="property">Precision</span>);</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Number</span>(<span class="built_in">parseFloat</span>(returnValue).<span class="title function_">toFixed</span>(round.<span class="property">Precision</span>));</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h2 id="if-分支优化"><a href="#if-分支优化" class="headerlink" title="if 分支优化"></a>if 分支优化</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 简单分支</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getUser</span>(<span class="params">name</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> userMap = &#123;</span><br><span class="line">        小刘: <span class="function">() =&gt;</span> <span class="string">&#x27;哥哥&#x27;</span>,</span><br><span class="line">        小红: <span class="function">() =&gt;</span> <span class="string">&#x27;妹妹&#x27;</span>,</span><br><span class="line">        陈龙: <span class="function">() =&gt;</span> <span class="string">&#x27;老师&#x27;</span>,</span><br><span class="line">        李龙: <span class="function">() =&gt;</span> <span class="string">&#x27;朋友&#x27;</span></span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">return</span> userMap[name] ? userMap[name]() : <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 复杂分支</span></span><br><span class="line"><span class="keyword">const</span> userList = [</span><br><span class="line">    [<span class="function">(<span class="params">name</span>) =&gt;</span> name.<span class="property">length</span> &gt; <span class="number">5</span>, <span class="function">() =&gt;</span> <span class="string">&#x27;名字太长&#x27;</span>],</span><br><span class="line">    [<span class="function">(<span class="params">name</span>) =&gt;</span> name[<span class="number">0</span>] == <span class="string">&#x27;陈&#x27;</span>, <span class="function">() =&gt;</span> <span class="string">&#x27;小陈&#x27;</span>],</span><br><span class="line">    [<span class="function">(<span class="params">name</span>) =&gt;</span> name == <span class="string">&#x27;大鹏&#x27;</span>, <span class="function">() =&gt;</span> <span class="string">&#x27;朋友&#x27;</span>]</span><br><span class="line">];</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getUserDescribe</span>(<span class="params">name</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> item = userList.<span class="title function_">find</span>(<span class="function"><span class="params">item</span> =&gt;</span> item[<span class="number">0</span>](name));</span><br><span class="line">    <span class="keyword">return</span> item ? item[<span class="number">1</span>]() : <span class="string">&#x27;&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="JS-继承模式"><a href="#JS-继承模式" class="headerlink" title="JS 继承模式"></a>JS 继承模式</h2><blockquote>
<p>按照几种继承模式的从最次的继承模式到最佳的继承模式的顺序去讲，讲出当前这种继承模式的利弊和相对前一种继承模式解决了什么问题，最关键的代码部分在哪里。</p>
</blockquote>
<ul>
<li><strong>原型链继承</strong><ul>
<li>实现：将子类的原型指向父类的实例，从而继承父类的私有属性和原型属性。</li>
<li>优点：子类实例能访问到父类新增的原型属性和方法、简单易用。</li>
<li>缺点：无法实现多继承(一个子类继承多个父类)、创建子类实例时无法向父类构造函数传参、存在子类实例共享父类引用属性而相互影响的问题。</li>
</ul>
</li>
<li><strong>父类构造函数继承</strong><ul>
<li>实现：子类构造函数中通过 call&#x2F;apply 调用父类构造函数来实现父类私有属性继承。</li>
<li>优点：可以实现多继承、创建子类实例时可以向父类传递参数、解决了原型链继承中子类实例共享父类引用属性的问题(引用类型数据会重新创建一份)。</li>
<li>缺点：每次创建子类实例时都要调用一次父类构造函数而影响性能、只继承父类的实例属性(私有属性)而没有继承父类的原型属性。</li>
</ul>
</li>
<li><strong>组合式继承 (原型链 + 构造函数)</strong><ul>
<li>实现：通过调用父类构造函数继承父类的属性并保留传参的优点，并通过 Object.create(Parent.prototype) 来创建继承了父类属性的对象并赋给子类原型，这样既让父类构造函数不用执行两次，又让子类继承了父类的原型方法。</li>
<li>本质：先创建子类的实例对象 this，然后通过 Parent.apply(this) 添加父类方法。</li>
<li>优点：构造函数继承的所有优点、父类构造函数只用执行一次。</li>
</ul>
</li>
<li><strong>ES6 class 继承</strong><ul>
<li>实现：使用 extends 关键字继承父类的原型属性，使用 static 关键字定义类的静态方法，调用 super 来继承父类的实例属性并且可以传参。</li>
<li>本质：先将父类实例对象的属性和方法添加到 this (所以必须先调用 super 方法)，然后再通过子类的构造函数修改 this。</li>
<li>优点：简单易用，不需要直接修改原型链来完成继承。</li>
</ul>
</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 组合式继承</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Parent</span> (sex) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">sex</span> = sex</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Parent</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">setSex</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Son</span> (name, age, sex) &#123;</span><br><span class="line">    <span class="title class_">Parent</span>.<span class="title function_">call</span>(<span class="variable language_">this</span>, sex)</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">name</span> = name</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">age</span> = age</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Son</span>.<span class="property"><span class="keyword">prototype</span></span> = <span class="title class_">Object</span>.<span class="title function_">create</span>(<span class="title class_">Parent</span>.<span class="property"><span class="keyword">prototype</span></span>)</span><br><span class="line"><span class="title class_">Son</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">constructor</span> = <span class="title class_">Son</span></span><br><span class="line"><span class="keyword">var</span> s1 = <span class="keyword">new</span> <span class="title class_">Son</span>(<span class="string">&#x27;Tony&#x27;</span>, <span class="number">25</span>, <span class="string">&#x27;男&#x27;</span>)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(s1)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// ES6 class 继承</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">A</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span> (sex) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">sex</span> = sex</span><br><span class="line">    &#125;</span><br><span class="line">    showSex () &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;父类方法&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">B</span> <span class="keyword">extends</span> <span class="title class_ inherited__">A</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span> (name, age, sex) &#123;</span><br><span class="line">        <span class="variable language_">super</span>(sex)</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">age</span> = age</span><br><span class="line">    &#125;</span><br><span class="line">    showSex () &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;子类方法&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> b = <span class="keyword">new</span> <span class="title function_">B</span>(<span class="string">&#x27;Tony&#x27;</span>, <span class="number">25</span>, <span class="string">&#x27;男&#x27;</span>)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(b)</span><br></pre></td></tr></table></figure>


<h2 id="this-指向"><a href="#this-指向" class="headerlink" title="this 指向"></a>this 指向</h2><blockquote>
<p>this 代表当前方法执行时自动生成的一个上下文对象。</p>
</blockquote>
<ul>
<li>默认绑定：非严格模式下指向 window，严格模式下绑定到 undefined。</li>
<li>隐式绑定：指向函数在调用位置的上下文对象，比如事件中指向操作元素。</li>
<li>显式绑定：call&#x2F;apply&#x2F;bind 显式地指定 this 绑定到作为传入参数的对象。</li>
<li>new 绑定：始终指向对象实例。new 是在内部新建空对象并添加构造函数的属性和方法。</li>
<li>箭头函数：指向定义时所在对象，因为它继承于外层第一个非箭头函数而使用外层 this。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 默认绑定</span></span><br><span class="line"><span class="keyword">let</span> fn = <span class="keyword">function</span> (<span class="params"></span>) &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>) &#125;</span><br><span class="line"><span class="keyword">let</span> obj = &#123; <span class="attr">name</span>: <span class="string">&#x27;哈哈哈&#x27;</span>, <span class="attr">fn</span>: fn &#125;</span><br><span class="line"><span class="title function_">fn</span>();       <span class="comment">// window</span></span><br><span class="line">obj.<span class="title function_">fn</span>();   <span class="comment">// obj</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 构造函数</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span> (name, age) &#123; </span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">age</span> = age;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>)  <span class="comment">// p：&#123;name: &quot;Tom&quot;, age: 20&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> p = <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="string">&#x27;Tony&#x27;</span>, <span class="number">20</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 箭头函数</span></span><br><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">    <span class="attr">a</span>: <span class="function">()=&gt;</span>&#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>) &#125;,       <span class="comment">// Window</span></span><br><span class="line">    <span class="attr">b</span>: <span class="keyword">function</span>(<span class="params"></span>)&#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>) &#125;  <span class="comment">// obj</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="各种位置"><a href="#各种位置" class="headerlink" title="各种位置"></a>各种位置</h2><ul>
<li><strong>offsetHeight</strong>：表示可视区域的高度，包含边框和滚动条。</li>
<li><strong>clientHeight</strong>：表示可视区域的高度，不包含边框和滚动条。</li>
<li><strong>scrollHeight</strong>：表示所有区域的高度，包含因为滚动被隐藏的部分。 </li>
<li><strong>clientTop</strong>：表示边框厚度，在未指定的情况下默认为 0。</li>
<li><strong>scrollTop</strong>：滚动后被隐藏的高度，相对于 offsetParent 父坐标距离顶端的高度。</li>
</ul>
<h2 id="平滑滚动"><a href="#平滑滚动" class="headerlink" title="平滑滚动"></a>平滑滚动</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">scrollToTop</span> = (<span class="params">element</span>) =&gt; &#123;</span><br><span class="line">    element.<span class="title function_">scrollIntoView</span>(&#123; <span class="attr">behavior</span>: <span class="string">&quot;smooth&quot;</span>, <span class="attr">block</span>: <span class="string">&quot;start&quot;</span> &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">scrollToBottom</span> = (<span class="params">element</span>) =&gt; &#123;</span><br><span class="line">    element.<span class="title function_">scrollIntoView</span>(&#123; <span class="attr">behavior</span>: <span class="string">&quot;smooth&quot;</span>, <span class="attr">block</span>: <span class="string">&quot;end&quot;</span> &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="复制功能"><a href="#复制功能" class="headerlink" title="复制功能"></a>复制功能</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">copyText</span> = <span class="keyword">async</span> (<span class="params">text</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">if</span> (navigator.<span class="property">clipboard</span> &amp;&amp; <span class="variable language_">window</span>.<span class="property">isSecureContext</span>) &#123;</span><br><span class="line">        <span class="keyword">await</span> navigator.<span class="property">clipboard</span>.<span class="title function_">writeText</span>(text)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> textArea = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;textArea&#x27;</span>)</span><br><span class="line">        textArea.<span class="property">value</span> = text</span><br><span class="line">        textArea.<span class="property">style</span>.<span class="property">width</span> = <span class="number">0</span></span><br><span class="line">        textArea.<span class="property">style</span>.<span class="property">position</span> = <span class="string">&#x27;fixed&#x27;</span></span><br><span class="line">        textArea.<span class="property">style</span>.<span class="property">left</span> = <span class="string">&#x27;-999px&#x27;</span></span><br><span class="line">        textArea.<span class="property">style</span>.<span class="property">top</span> = <span class="string">&#x27;10px&#x27;</span></span><br><span class="line">        textArea.<span class="title function_">setAttribute</span>(<span class="string">&#x27;readonly&#x27;</span>, <span class="string">&#x27;readonly&#x27;</span>)</span><br><span class="line">        <span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(textArea)</span><br><span class="line">        textArea.<span class="title function_">select</span>()</span><br><span class="line">        <span class="variable language_">document</span>.<span class="title function_">execCommand</span>(<span class="string">&#x27;copy&#x27;</span>)</span><br><span class="line">        <span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">removeChild</span>(textArea)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="防抖和节流"><a href="#防抖和节流" class="headerlink" title="防抖和节流"></a>防抖和节流</h2><blockquote>
<p>在网页实际运行的某些场景下，有些事件会被连续触发而频繁进行 DOM 操作和资源加载，严重影响了网页性能，甚至会造成浏览器崩溃。两者都是针对连续触发的某个行为，区别在于是要优化到减少它的执行次数还是只执行一次。</p>
</blockquote>
<ul>
<li><strong>防抖</strong>：将一个弹簧连续按下但只会在最后放手的一瞬反弹，即我们希望高频事件只执行一次而实现回调函数的延时执行。常见的应用场景有：搜索框输入内容时 keyup、浏览器窗口调整时 resize。</li>
<li><strong>节流</strong>：一个水龙头在滴水时保持 一滴水&#x2F;s 的频率。即我们希望高频事件以一定频率重复调用，减少函数的执行次数。常见的应用场景有：拖拽元素时 drag、监听滚动时 scroll、鼠标移动时 mousemove、手指滑动时 touchmove。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 防抖：n 秒内高频事件再次被触发则重新执行。</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">debounce</span>(<span class="params">callback, delay=<span class="number">200</span></span>)&#123;</span><br><span class="line">    <span class="keyword">let</span> timer = <span class="literal">null</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">if</span> (timer) <span class="built_in">clearTimeout</span>(timer);</span><br><span class="line">        timer = <span class="built_in">setTimeout</span>(<span class="function">()=&gt;</span>&#123;</span><br><span class="line">            callback.<span class="title function_">apply</span>(<span class="variable language_">this</span>, <span class="variable language_">arguments</span>);</span><br><span class="line">            timer = <span class="literal">null</span>;</span><br><span class="line">        &#125;, delay);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> handleSeach = <span class="title function_">debounce</span>(seachAjax, <span class="number">500</span>)</span><br><span class="line">input.<span class="title function_">addEventListener</span>(<span class="string">&quot;keyup&quot;</span>, <span class="function"><span class="params">e</span>=&gt;</span>&#123; <span class="title function_">handleSeach</span>(e.<span class="property">target</span>.<span class="property">value</span>)&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 节流：n 秒内只会执行一次。</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">throttle</span>(<span class="params">callback, duration=<span class="number">200</span></span>)&#123;</span><br><span class="line">    <span class="keyword">let</span> timer = <span class="literal">null</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">if</span> (timer) <span class="keyword">return</span>;</span><br><span class="line">        timer = <span class="built_in">setTimeout</span>(<span class="function">()=&gt;</span>&#123;</span><br><span class="line">            callback.<span class="title function_">apply</span>(<span class="variable language_">this</span>, <span class="variable language_">arguments</span>);</span><br><span class="line">            timer = <span class="literal">null</span>;</span><br><span class="line">        &#125;, duration);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> handleScroll = <span class="title function_">throttle</span>(handleScroll)</span><br><span class="line"><span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;touchmove&quot;</span>, handleScroll);</span><br></pre></td></tr></table></figure>


<h2 id="内存泄漏"><a href="#内存泄漏" class="headerlink" title="内存泄漏"></a>内存泄漏</h2><ul>
<li>原因：对象存储的内存空间在使用完毕后并没有重置为 null 释放，导致该内存单元在离开当前作用域前无法被释放或者被垃圾回收。</li>
<li>出现场景：setTimeout 首个参数使用字符串而非函数、闭包、意外的全局变量、未被清空的定时器、未被销毁的事件监听、DOM 引用等。</li>
<li>解决方案：不要动态绑定事件、不要给动态元素绑定事件而通过事件冒泡在父容器监听事件、动态时则必须提供 destroy 方法、尽量单例化、少创建 dom、少绑事件。</li>
</ul>
<h2 id="内存机制"><a href="#内存机制" class="headerlink" title="内存机制"></a>内存机制</h2><ul>
<li>内存：由可读写单元组成而表示一片可操作空间。</li>
<li>内存管理：JS 解释器对新建的字符串和对象动态分配一块内存空间并自动管理，但由于没有相关 API 而无法像 C&#x2F;C++ 主动调用。</li>
<li>垃圾回收机制：JS 执行引擎将垃圾占用的对象空间回收的过程。对象创建时自动分配一块内存空间，对象不再被引用或者根作用域不能被访问时会自动释放它占用的内存。</li>
</ul>
<h2 id="堆栈溢出"><a href="#堆栈溢出" class="headerlink" title="堆栈溢出"></a>堆栈溢出</h2><ul>
<li><strong>递归</strong>：指一个函数不断的调用自身。它将原来的问题转化为更小的同一问题来求解，只需要少量代码就可以完成多次重复计算，大大地减少了程序的代码量。</li>
<li><strong>堆栈溢出</strong>：JS 引擎每调用一个函数时都会为其创建执行上下文并压入调用栈，执行函数代码时如果调用其它函数则创建新函数的执行上下文并压入栈顶。每个函数通过栈分配一定空间的数据块来保存参数、返回值等临时信息，等到函数执行完成时才出栈，但是当用来分配的调用栈空间被占满时会导致数据覆盖问题，即递归中经常发生的栈溢出错误 stackOverflow。</li>
<li><strong>栈溢出的解决方案</strong>：使用闭包 (每次调用时返回一个匿名函数，相关的参数和局部变量将会被释放而不会额外增加堆栈大小)、优化调用、尾递归 (添加一个参数，记录递归次数)。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 递归示例</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Fibonacci</span> (n) &#123;</span><br><span class="line">  <span class="keyword">if</span> ( n &lt;= <span class="number">2</span> ) &#123;<span class="keyword">return</span> <span class="number">1</span>&#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Fibonacci</span>(n - <span class="number">1</span>) + <span class="title class_">Fibonacci</span>(n - <span class="number">2</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 栈溢出</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">factorial</span>(<span class="params">n</span>) &#123;</span><br><span class="line">  <span class="keyword">if</span> (n === <span class="number">1</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">  <span class="keyword">return</span> n * <span class="title function_">factorial</span>(n - <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 尾递归</span></span><br><span class="line"><span class="keyword">let</span> count = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">factorial</span>(<span class="params">n</span>) &#123;</span><br><span class="line">    count ++;</span><br><span class="line">    <span class="keyword">if</span> (count &gt; <span class="number">1000</span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;超过了最大调用次数&#x27;</span>);</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (n === <span class="number">1</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">return</span> n * <span class="title function_">factorial</span>(n - <span class="number">1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="异步任务"><a href="#异步任务" class="headerlink" title="异步任务"></a>异步任务</h2><blockquote>
<p>先主线程后异步任务队列、先微任务再宏任务。</p>
</blockquote>
<ol>
<li>JS 引擎将所有操作分为 同步任务、异步任务。</li>
<li>同步任务进入主线程，然后直接按顺序执行。</li>
<li>异步任务进入工作线程，当满足触发条件后推入任务队列。</li>
<li>事件循环机制：主线程执行完所有同步任务之后空闲时，重复去任务队列中查看是否有可执行的异步任务，有则推入主进程的执行栈。<br>1. 执行一个宏任务（栈中没有就从事件队列中获取）。<br>2. 执行过程中如果遇到微任务，就将它添加到微任务的任务队列中。<br>3. 宏任务执行完毕后，立即执行当前微任务队列中的所有微任务（依次执行）。<br>4. 当前宏任务执行完毕，开始检查渲染，然后 GUI 线程接管渲染。<br>5. 渲染完毕后，JS 线程继续接管，开始下一个宏任务（从任务队列中获取）。</li>
</ol>
<h2 id="异步编程"><a href="#异步编程" class="headerlink" title="异步编程"></a>异步编程</h2><ul>
<li><strong>回调函数</strong>：解决了同步问题但可能存在回调地狱，不能使用 try catch、return。</li>
<li><strong>Promise</strong>：同步的立即执行函数，解决了回调地狱但无法取消，需要回调函数捕获错误。</li>
<li><strong>Generator</strong>：多个线程互相协作来完成异步任务的异步编程方案，主要特点是线程 A 执行到某处之后暂停执行并等到线程 B 执行完毕后继续执行。</li>
<li><strong>Async&#x2F;Await</strong>：本质是一个自执行的 generate 函数，以同步方式实现异步代码提高了代码的可维护性，async 函数遇到 await 时会先执行异步操作并返回一个 Promise 对象。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span>* <span class="title function_">gen</span>(<span class="params">x</span>) &#123;</span><br><span class="line">    <span class="keyword">var</span> y = <span class="keyword">yield</span> x + <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">return</span> y;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> g = <span class="title function_">gen</span>(<span class="number">1</span>);</span><br><span class="line">g.<span class="title function_">next</span>().<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> g.<span class="title function_">next</span>(res)).<span class="title function_">then</span>()</span><br></pre></td></tr></table></figure>

<h2 id="构建工具"><a href="#构建工具" class="headerlink" title="构建工具"></a>构建工具</h2><ul>
<li>手工构建：代码压缩、图片压缩、代码合并</li>
<li>自动化构建：基于任务流的构建工具 <code>Grunt/Gulp</code> 自动化执行编译压缩合并等操作。</li>
<li>模块化构建：模块打包器 <code>Webpack/Rollup</code> 将多个文件打包为一个，Rollup 去掉未用代码。</li>
<li>Bundless 构建：支持按需编译的前端调试器 <code>Snowpack/Vite</code> 实现轻量高效的构建。</li>
<li>应用场景：项目型推荐可靠的 Webpack，类库型推荐 Rollup，非核心项目可以尝试 Vite。</li>
</ul>
<h2 id="模块循环"><a href="#模块循环" class="headerlink" title="模块循环"></a>模块循环</h2><ul>
<li><strong>模块的循环引用主要需要处理避免死循环和输出值两个问题</strong>：CommonJS 导出的值的拷贝而无法实现两个模块的同步更新，在每次 require 都会先读取<strong>模块缓存</strong>而只会执行一次模块。ES Module 导出的是值的内存地址而实现了动态绑定，在代码执行前的预处理时会根据 import&#x2F;export 构建描述依赖关系的<strong>模块地图</strong>并在每个节点标注包含执行状态和内存地址的<strong>模块记录</strong>，每次 import 时都会检查地图并通过模块记录获取内存地址或者去执行新模块。</li>
<li><strong>export、module.export</strong>：指向同一块内存而且模块实际导出的是这块内存的地址，注意本质执行的 module.export，所以直接给 export 赋值会导致指向丢失。</li>
<li><strong>模块查找</strong>：<strong>核心模块</strong> – node 将其已经编译成二进制代码而可以直接使用标识符 fs&#x2F;http、<strong>自定义模块</strong> – require 将相对路径转化为真实路径而找到模块、<strong>第三方模块</strong> – 根据模块变量 module.paths 路径依次查找 当前目录node_modules、父级目录  node_modules、根目录 node_modules。如果在 node_modules 找到对应包则会根据 package.json main 字段找到入口文件，没有 main 则查找 index.js&#x2F;index.json&#x2F;index.node。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// CommonJS VS ES-Module：index.js、a.js、b.js</span></span><br><span class="line"><span class="keyword">var</span> a = <span class="built_in">require</span>(<span class="string">&#x27;./a&#x27;</span>)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(a)            <span class="comment">// 3、&#123; a: &#x27;修改值--a&#x27; &#125;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">a</span> = <span class="string">&#x27;原始值--a&#x27;</span></span><br><span class="line"><span class="keyword">var</span> b = <span class="built_in">require</span>(<span class="string">&#x27;./b&#x27;</span>)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(b)            <span class="comment">// 2、&#123; b: &#x27;修改值--b&#x27; &#125;</span></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">a</span> = <span class="string">&#x27;修改值--a&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">b</span> =<span class="string">&#x27;原始值-b&#x27;</span></span><br><span class="line"><span class="keyword">var</span> a = <span class="built_in">require</span>(<span class="string">&#x27;./a&#x27;</span>)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(a)            <span class="comment">// 1、&#123; a: &#x27;原始值--a&#x27; &#125;</span></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">b</span> = <span class="string">&#x27;修改值--b&#x27;</span>     </span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> a <span class="keyword">from</span> <span class="string">&#x27;./a.js&#x27;</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(a)           <span class="comment">// 3、&#123; a: &#x27;修改值--a&#x27; &#125;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> a = <span class="string">&quot;原始值--a&quot;</span></span><br><span class="line"><span class="keyword">export</span> &#123; a &#125;</span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> b <span class="keyword">from</span> <span class="string">&quot;./b.js&quot;</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(b)           <span class="comment">// 2、&#123; b: &#x27;修改值--b&#x27; &#125;</span></span><br><span class="line">a = <span class="string">&quot;修改值-a&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> b = <span class="string">&quot;原始值--b&quot;</span></span><br><span class="line"><span class="keyword">export</span> &#123; b &#125;</span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> a <span class="keyword">from</span> <span class="string">&quot;./a.js&quot;</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(a)       <span class="comment">// 1、空内存：&#123; a: uninitialized &#125;</span></span><br><span class="line">b = <span class="string">&quot;修改值--b&quot;</span>                </span><br></pre></td></tr></table></figure>


<h2 id="apply、call、bind"><a href="#apply、call、bind" class="headerlink" title="apply、call、bind"></a>apply、call、bind</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123; <span class="attr">name</span>: <span class="string">&#x27;linxin&#x27;</span> &#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">f</span> (x, y) &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>) &#125;</span><br><span class="line"></span><br><span class="line">f.<span class="title function_">apply</span>(a, [<span class="number">1</span>, <span class="number">2</span>])  <span class="comment">// 参数为数组、函数直接执行</span></span><br><span class="line">f.<span class="title function_">call</span>(a, <span class="number">1</span>, <span class="number">2</span>)     <span class="comment">// 参数为值、函数直接执行</span></span><br><span class="line">f.<span class="title function_">bind</span>(a, <span class="number">1</span>, <span class="number">2</span>)()   <span class="comment">// 参数为值或数组、函数返回一个绑定新 this 的函数但不执行</span></span><br></pre></td></tr></table></figure>


<h2 id="箭头函数和普通函数"><a href="#箭头函数和普通函数" class="headerlink" title="箭头函数和普通函数"></a>箭头函数和普通函数</h2><blockquote>
<p>箭头函数是普通函数的简写，可以更优雅的定义一个函数，和普通函数的差异如下：</p>
</blockquote>
<ul>
<li>函数体内的 this 对象，是定义时所在的对象，而不是使用时所在的对象。</li>
<li>不可以使用 arguments 对象，函数体内不存在该对象但可用 rest 代替。</li>
<li>不可以使用 yield 命令，因此箭头函数不能用作 Generator 函数。</li>
<li>不可以使用 new 命令：没有自己的 this 而无法调用 call&#x2F;apply、没有 prototype 属性。</li>
</ul>
<h2 id="MVC、MVP、MVVM"><a href="#MVC、MVP、MVVM" class="headerlink" title="MVC、MVP、MVVM"></a>MVC、MVP、MVVM</h2><ul>
<li><strong>MVC</strong>：View、Model 直接绑定，因此很多 view 可以修改多个 model 而变得混乱，交互增加导致代码不好维护。</li>
<li><strong>MVP</strong>：View 绑定事件的事件驱动机制，并通过 Presenter 实现分离和通信。它定义了 View、Presenter 之间的接口，需要维护 Presenter 的内部实现。</li>
<li><strong>MVVM</strong>：View、Model 分别通过 ViewModel 的 DOM-Listeners、Data-Bindings 绑定事件和监听数据而实现了双向绑定。它实现了数据与视图的分离，通过数据来驱动视图，开发者只需要关心数据变化 (DOM 操作被封装了)。</li>
</ul>
<h2 id="Set、Map、WeakSet、WeakMap"><a href="#Set、Map、WeakSet、WeakMap" class="headerlink" title="Set、Map、WeakSet、WeakMap"></a>Set、Map、WeakSet、WeakMap</h2><ul>
<li><strong>Set</strong>：成员不能重复、只有键值而没有键名、可以遍历。</li>
<li><strong>WeakSet</strong>：成员都是对象、成员都是弱引用而不计入垃圾回收机制、不能遍历。</li>
<li><strong>Map</strong>：本质是键值对的集合、可以遍历、可以和各种数据格式转换。</li>
<li><strong>WeakMap</strong>：只接收对象为键名、键名指向的对象不计入垃圾回收机制、不能遍历。</li>
</ul>
<h2 id="webpack-loader、plugin"><a href="#webpack-loader、plugin" class="headerlink" title="webpack loader、plugin"></a>webpack loader、plugin</h2><ul>
<li><strong>loader</strong>：一个转换器，将 A 文件进行编译成 B 文件，属于单纯的文件转换过程。</li>
<li><strong>plugin</strong>：一个扩展器，它丰富了 webpack 本身，针对的是 loader 结束后 webpack 打包的整个过程，它并不直接操作文件，而是基于事件机制工作，会监听 webpack 打包过程中的某些节点，执行广泛的任务。</li>
</ul>
<h1 id="三、JS-框架"><a href="#三、JS-框架" class="headerlink" title="三、JS 框架"></a>三、JS 框架</h1><h2 id="Angular、React、Vue"><a href="#Angular、React、Vue" class="headerlink" title="Angular、React、Vue"></a>Angular、React、Vue</h2><h3 id="区别"><a href="#区别" class="headerlink" title="区别"></a>区别</h3><ul>
<li><strong>Vue</strong>：双向数据流，vuex 集中管理数据，有指令且能自定义指令，双向数据绑定。</li>
<li><strong>React</strong>：单项数据流，操作虚拟 dom，redux 集中管理数据，无指令。</li>
<li><strong>Angular</strong>：单项数据流，学习成本高而且性能稍差于其它两个，双向绑定原理不同 vue。</li>
</ul>
<h3 id="Vue"><a href="#Vue" class="headerlink" title="Vue"></a>Vue</h3><blockquote>
<p>尤雨溪开发的用于构建用户界面的一个渐进式 JS 库、数据驱动的组件系统、轻量高效的前端组件化方案，专注于视图层而不是一个全能框架。</p>
</blockquote>
<ul>
<li>特点：轻量级、双向数据绑定、数据驱动视图、视图与数据分离。</li>
<li>优点：渐进式构建能力、简单语法、更快的渲染速度和更小的体积。</li>
<li>缺点：不支持低端浏览器、首页加载缓慢，适用于中小型项目。</li>
</ul>
<h3 id="React"><a href="#React" class="headerlink" title="React"></a>React</h3><blockquote>
<p>Facebook 开源的一个用于动态构建用户界面的 JS 库、需要集成 Redux 等库才能实现复杂应用的非完整解决方案。</p>
</blockquote>
<ul>
<li>特点：采用声明式描述应用、引入 Virtual DOM 和 react-diff 算法实现高效渲染、通过 JSX 语法实现组件化、单向数据流。</li>
<li>优点：高效渲染、标准 API 解决了跨浏览器兼容问题、代码更加模块化。</li>
<li>缺点：专注于视图层而需要集成其它库，不适合大型项目。</li>
</ul>
<h3 id="Angular"><a href="#Angular" class="headerlink" title="Angular"></a>Angular</h3><blockquote>
<p>Google 开源的一个基于 TypeScript 的 JS 框架、最完善的前端工程框架。</p>
</blockquote>
<ul>
<li>特点：良好的结构程序、双向数据绑定(脏检查机制)、依赖注入、服务等。</li>
<li>优点：兼容所有平台、通过依赖注入实现注入服务、大型应用中实现静态类型检查。</li>
<li>缺点：验证功能错误信息显示比较薄弱，需要写很多模板标签。ngView 只能有一个，不能嵌套多个视图。比较笨重，没有让用户选择的轻量级版本，只适合大型项目。</li>
</ul>
<h3 id="数据更新机制"><a href="#数据更新机制" class="headerlink" title="数据更新机制"></a>数据更新机制</h3><ul>
<li><strong>Vue 依赖收集</strong>：每个组件都有自己的 viewModel 实例，每个实例有数据监听、元素操作、作用域。当数据更新时只会涉及自身作用域，所以大量数据更新时需要重新收集依赖而比较慢。</li>
<li><strong>Angular 脏检查</strong>：存储所有变量的值，数据更新时对比旧值跟新值，不相等则更新对应视图。</li>
<li><strong>React Virtual DOM</strong>：数据更新时先修改虚拟 DOM，通过新旧对比获取最小修改量之后渲染到真实元素，大量数据更新时性能不好，但为跨平台等将 dom 渲染到其它场景提供了思路。</li>
<li>性能之初始数据渲染：虚拟 &gt; 脏检查 &gt;&#x3D; 依赖收集。</li>
<li>性能之小量数据更新：依赖收集 &gt;&gt; 虚拟–优化 &gt; 脏检查–无法优化 &gt; 虚拟–无优化。</li>
<li>性能之大量数据更新：脏检查 优化 &gt;&#x3D; 依赖收集–优化 &gt; 虚拟–无法优化。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Virtual DOM：本质是一个描述页面节点的对象</span></span><br><span class="line"><span class="keyword">var</span> element = &#123;</span><br><span class="line">    <span class="attr">tag</span>: <span class="string">&#x27;ul&#x27;</span>,              <span class="comment">// 节点标签名</span></span><br><span class="line">    <span class="attr">attrs</span>: &#123; <span class="attr">id</span>: <span class="string">&#x27;list&#x27;</span> &#125;,  <span class="comment">// 键值对存储的 DOM 属性</span></span><br><span class="line">    <span class="attr">children</span>: [             <span class="comment">// 当前节点的子节点</span></span><br><span class="line">        &#123;<span class="attr">tag</span>: <span class="string">&#x27;li&#x27;</span>, <span class="attr">attrs</span>: &#123;<span class="attr">class</span>: <span class="string">&#x27;item&#x27;</span>&#125;, <span class="attr">children</span>: [<span class="string">&quot;Item 1&quot;</span>]&#125;,</span><br><span class="line">        &#123;<span class="attr">tag</span>: <span class="string">&#x27;li&#x27;</span>, <span class="attr">attrs</span>: &#123;<span class="attr">class</span>: <span class="string">&#x27;item&#x27;</span>&#125;, <span class="attr">children</span>: [<span class="string">&quot;Item 2&quot;</span>]&#125;,</span><br><span class="line">        &#123;<span class="attr">tag</span>: <span class="string">&#x27;li&#x27;</span>, <span class="attr">attrs</span>: &#123;<span class="attr">class</span>: <span class="string">&#x27;item&#x27;</span>&#125;, <span class="attr">children</span>: [<span class="string">&quot;Item 3&quot;</span>]&#125;</span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 对应的 HTML 节点</span></span><br><span class="line">&lt;ul id=<span class="string">&#x27;list&#x27;</span>&gt;</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&#x27;item&#x27;</span>&gt;</span>Item 1<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&#x27;item&#x27;</span>&gt;</span>Item 2<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&#x27;item&#x27;</span>&gt;</span>Item 3<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span><br><span class="line">&lt;/ul&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 实现原理 </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 1、通过构造函数 Element 构建虚拟 DOM。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 2、通过 render 方法转换为真实 DOM 并插入到页面。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 3、页面数据更新时通过 diff 方法对比新旧的虚拟 DOM 得到更新补丁 patches。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 4、深度遍历真实 DOM 节点，通过 patches 找到当前节点更新操作并更新页面。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">var</span> tree = <span class="title function_">el</span>(<span class="string">&#x27;div&#x27;</span>, &#123;<span class="string">&#x27;id&#x27;</span>: <span class="string">&#x27;container&#x27;</span>&#125;, [</span><br><span class="line">    <span class="title function_">el</span>(<span class="string">&#x27;h1&#x27;</span>, &#123;<span class="attr">style</span>: <span class="string">&#x27;color: blue&#x27;</span>&#125;, [<span class="string">&#x27;simple virtal dom&#x27;</span>]),</span><br><span class="line">    <span class="title function_">el</span>(<span class="string">&#x27;p&#x27;</span>, [<span class="string">&#x27;Hello, virtual-dom&#x27;</span>]),</span><br><span class="line">    <span class="title function_">el</span>(<span class="string">&#x27;ul&#x27;</span>, [<span class="title function_">el</span>(<span class="string">&#x27;li&#x27;</span>)])</span><br><span class="line">])</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> root = tree.<span class="title function_">render</span>()</span><br><span class="line"><span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(root)</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> newTree = <span class="title function_">el</span>(<span class="string">&#x27;div&#x27;</span>, &#123;<span class="string">&#x27;id&#x27;</span>: <span class="string">&#x27;container&#x27;</span>&#125;, [</span><br><span class="line">    <span class="title function_">el</span>(<span class="string">&#x27;h1&#x27;</span>, &#123;<span class="attr">style</span>: <span class="string">&#x27;color: red&#x27;</span>&#125;, [<span class="string">&#x27;simple virtal dom&#x27;</span>]),</span><br><span class="line">    <span class="title function_">el</span>(<span class="string">&#x27;p&#x27;</span>, [<span class="string">&#x27;Hello, virtual-dom&#x27;</span>]),</span><br><span class="line">    <span class="title function_">el</span>(<span class="string">&#x27;ul&#x27;</span>, [<span class="title function_">el</span>(<span class="string">&#x27;li&#x27;</span>), <span class="title function_">el</span>(<span class="string">&#x27;li&#x27;</span>)])</span><br><span class="line">])</span><br><span class="line"><span class="keyword">var</span> patches = <span class="title function_">diff</span>(tree, newTree)</span><br><span class="line"><span class="title function_">patch</span>(root, patches)</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Element</span> (tag, attrs, children) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">tagName</span> = tagName</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">props</span> = props</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">children</span> = children</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">el</span>(<span class="params">tag, attrs, children</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Element</span>(tag, attrs, children)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Element</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">render</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="keyword">let</span> el = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="variable language_">this</span>.<span class="property">tag</span>);</span><br><span class="line">    <span class="keyword">let</span> attrs = <span class="variable language_">this</span>.<span class="property">attrs</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> attrName <span class="keyword">in</span> attrs) &#123;</span><br><span class="line">        <span class="keyword">let</span> attrValue = attrs[attrName];</span><br><span class="line">        el.<span class="title function_">setAttribute</span>(attrName,attrValue);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">let</span> children = <span class="variable language_">this</span>.<span class="property">children</span> || [];</span><br><span class="line">    children.<span class="title function_">forEach</span>( <span class="function"><span class="params">child</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// 判断子元素是不是节点，是递归继续渲染，否则创建一个文本节点</span></span><br><span class="line">        <span class="keyword">let</span> childEle = (child <span class="keyword">instanceof</span> <span class="title class_">Element</span>) ? child.<span class="title function_">render</span>() : </span><br><span class="line">        <span class="variable language_">document</span>.<span class="title function_">createTextNode</span>(child);</span><br><span class="line">        el.<span class="title function_">appendChild</span>(childEle);</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">return</span> el;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">diff</span> (oldTree, newTree) &#123;</span><br><span class="line">    <span class="keyword">var</span> index = <span class="number">0</span>      <span class="comment">// 当前节点的标志</span></span><br><span class="line">    <span class="keyword">var</span> patches = &#123;&#125;   <span class="comment">// 记录每个节点差异的对象</span></span><br><span class="line">    <span class="title function_">dfsWalk</span>(oldTree, newTree, index, patches)</span><br><span class="line">    <span class="keyword">return</span> patches</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">dfsWalk</span> (oldNode, newNode, index, patches) &#123;</span><br><span class="line">    patches[index] = [&#123;</span><br><span class="line">        <span class="attr">type</span>: <span class="variable constant_">REORDER</span>,  <span class="comment">// 具体差异部分已省略</span></span><br><span class="line">        <span class="attr">moves</span>: [&#123;remove or insert&#125;, &#123;remove or insert&#125;, ...]</span><br><span class="line">    &#125;]</span><br><span class="line">    <span class="title function_">diffChildren</span>(oldNode.<span class="property">children</span>, newNode.<span class="property">children</span>, index, patches)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">diffChildren</span> (oldChildren, newChildren, index, patches) &#123;</span><br><span class="line">    <span class="keyword">var</span> leftNode = <span class="literal">null</span></span><br><span class="line">    <span class="keyword">var</span> currentNodeIndex = index</span><br><span class="line">    oldChildren.<span class="title function_">forEach</span>(<span class="keyword">function</span> (<span class="params">child, i</span>) &#123;</span><br><span class="line">        <span class="keyword">var</span> newChild = newChildren[i]</span><br><span class="line">        currentNodeIndex = (leftNode &amp;&amp; leftNode.<span class="property">count</span>)  <span class="comment">// 计算节点的标识</span></span><br><span class="line">          ? currentNodeIndex + leftNode.<span class="property">count</span> + <span class="number">1</span></span><br><span class="line">          : currentNodeIndex + <span class="number">1</span></span><br><span class="line">        <span class="title function_">dfsWalk</span>(child, newChild, currentNodeIndex, patches) <span class="comment">// 遍历子节点</span></span><br><span class="line">        leftNode = child</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">patch</span> (node, patches) &#123;</span><br><span class="line">    <span class="keyword">var</span> walker = &#123;<span class="attr">index</span>: <span class="number">0</span>&#125;</span><br><span class="line">    <span class="title function_">dfsWalk</span>(node, walker, patches)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">dfsWalk</span> (node, walker, patches) &#123;</span><br><span class="line">    <span class="keyword">var</span> currentPatches = patches[walker.<span class="property">index</span>]  <span class="comment">// 获取当前节点的差异</span></span><br><span class="line">    <span class="keyword">var</span> len = node.<span class="property">childNodes</span> ? node.<span class="property">childNodes</span>.<span class="property">length</span> : <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; len; i++) &#123;             <span class="comment">// 深度遍历子节点</span></span><br><span class="line">        <span class="keyword">var</span> child = node.<span class="property">childNodes</span>[i]</span><br><span class="line">        walker.<span class="property">index</span>++</span><br><span class="line">        <span class="title function_">dfsWalk</span>(child, walker, patches)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (currentPatches) &#123;</span><br><span class="line">        <span class="title function_">applyPatches</span>(node, currentPatches)     <span class="comment">// 对当前节点操作 DOM</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">applyPatches</span> (node, currentPatches) &#123;</span><br><span class="line">    currentPatches.<span class="title function_">forEach</span>(<span class="keyword">function</span> (<span class="params">patch</span>) &#123;</span><br><span class="line">        <span class="keyword">switch</span> (patch.<span class="property">type</span>) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="attr">REPLACE</span>:</span><br><span class="line">                node.<span class="property">parentNode</span>.<span class="title function_">replaceChild</span>(patch.<span class="property">node</span>.<span class="title function_">render</span>(), node)</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            <span class="keyword">case</span> <span class="attr">REORDER</span>:</span><br><span class="line">                <span class="title function_">reorderChildren</span>(node, patch.<span class="property">moves</span>)</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            <span class="keyword">case</span> <span class="attr">PROPS</span>:</span><br><span class="line">                <span class="title function_">setProps</span>(node, patch.<span class="property">props</span>)</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            <span class="keyword">case</span> <span class="attr">TEXT</span>:</span><br><span class="line">                node.<span class="property">textContent</span> = patch.<span class="property">content</span></span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            <span class="attr">default</span>:</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;Unknown patch type &#x27;</span> + patch.<span class="property">type</span>)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="Vue-1"><a href="#Vue-1" class="headerlink" title="Vue"></a>Vue</h2><h3 id="单向数据流"><a href="#单向数据流" class="headerlink" title="单向数据流"></a>单向数据流</h3><blockquote>
<p>数据流指组件之间的数据流动，vue、react 遵循数据只能由外层组件向内层组件传递的单向数据流。特点是子组件不能直接修改从父组件传递过来的数据，否则一个子组件修改数据就会导致所有子组件变化。优点是所有状态的改变可记录、可跟踪，组件数据只有唯一的入口和出口，有利于代码维护。缺点是写起来不太方便，变更时需要创建各种 action 来维护对应的 state。</p>
</blockquote>
<h3 id="双向绑定数据"><a href="#双向绑定数据" class="headerlink" title="双向绑定数据"></a>双向绑定数据</h3><blockquote>
<p>单双向绑定指 view、model 之间的映射关系，和数据流无关。优点是在表单交互较多的场景下，会简化大量与业务无关的代码。缺点是无法追踪局部状态的变化，增加了 debug 难度。react 采取单向绑定，vue 支持单向绑定(<code>插值，v-bind</code>) 和双向绑定(<code>v-model</code>)。</p>
</blockquote>
<ul>
<li><strong>实现原理</strong>：vue2.0 采用数据劫持结合发布者-订阅者模式的方式，通过 Object.defineProperty() 来劫持各个属性的 setter、getter 操作，在数据变动时发布消息给订阅者，触发相应监听回调。</li>
<li><strong>实现流程</strong> <ul>
<li><strong>1、模板解析为 render 函数</strong>：函数包含所有的模板信息并返回一个虚拟 DOM，模板的 data 和指令变成了 JS 变量和 JS 逻辑。</li>
<li><strong>2、响应式监听</strong>：通过 Object.defineProperty 设置对象的 get&#x2F;set 实现监听 data 的属性变化，然后将 data 属性代理到实例对象 vm。</li>
<li><strong>3、页面渲染</strong>：通过 updateComponent() 将模板渲染为 html。首次渲染时直接渲染虚拟 DOM，data 属性变化触发重新渲染时对比新旧节点后局部渲染。</li>
</ul>
</li>
<li><strong>实现方式</strong><ul>
<li><strong>发布者-订阅者模式</strong>：一般通过 sub、pub 的方式实现数据和视图的绑定监听，更新数据 <code>vm.set(&#39;property&#39;, value)</code>。</li>
<li><strong>脏值检查</strong>：angular 在指定事件触发时进入脏值检测，通过对比新旧数据来决定是否更新视图，它只对改变的数据进行更新元素。</li>
<li><strong>数据劫持</strong>：vue2.0 通过 <code>Object.defineProperty()</code> 来监听对象各个属性的 getter、setter，属性改变时触发回调。</li>
<li><strong>ES6 Proxy</strong>：vue3.0 用来替代 Object.defineProperty，因为它可以劫持整个对象而不需要遍历对象的所有属性。</li>
</ul>
</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> data) &#123;</span><br><span class="line">    (<span class="keyword">function</span> (<span class="params">key</span>) &#123;</span><br><span class="line">        <span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(obj, key, &#123;</span><br><span class="line">            <span class="attr">get</span>: <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">                <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;get&#x27;</span>, key);</span><br><span class="line">                <span class="keyword">return</span> data[key];</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="attr">set</span>: <span class="keyword">function</span>(<span class="params">newVal</span>) &#123;</span><br><span class="line">                <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;set&#x27;</span>, newVal);</span><br><span class="line">                data[key] = newVal;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;)(key)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> data = <span class="keyword">new</span> <span class="title class_">Proxy</span>(&#123;</span><br><span class="line">    <span class="attr">get</span>: <span class="keyword">function</span> (<span class="params">obj, key</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> obj[key];</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">set</span>: <span class="keyword">function</span> (<span class="params">obj, key, val</span>) &#123;</span><br><span class="line">        obj[key] = val;</span><br><span class="line">        <span class="title function_">scan</span>();</span><br><span class="line">        <span class="keyword">return</span> obj[key];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h3 id="双向绑定和-vuex-是否冲突"><a href="#双向绑定和-vuex-是否冲突" class="headerlink" title="双向绑定和 vuex 是否冲突"></a>双向绑定和 vuex 是否冲突</h3><blockquote>
<p>严格模式下使用时，Vuex state 上使用 v-model 会导致出错。解决方案如下：</p>
</blockquote>
<ul>
<li>使用带有 setter 的双向绑定计算属性。</li>
<li><code>&lt;Input&gt;</code> 绑定 value，然后监听 input&#x2F;change 事件并在事件回调中调用方法。</li>
</ul>
<h3 id="Proxy-替代-Object-defineProperty"><a href="#Proxy-替代-Object-defineProperty" class="headerlink" title="Proxy 替代 Object.defineProperty"></a>Proxy 替代 Object.defineProperty</h3><ul>
<li><strong>Object.defineProperty</strong>：无法低耗费的监听到数组下标的变化，导致通过数组下标添加元素时不能实时响应。只能劫持对象的属性，从而需要对每个对象、每个属性进行遍历，如果属性值是对象则还需要深度遍历。</li>
<li><strong>Proxy</strong>：可以劫持整个对象并返回一个新对象。可以代理对象、数组、动态增加的属性。</li>
</ul>
<h3 id="如何监控到属性修改并触发警告"><a href="#如何监控到属性修改并触发警告" class="headerlink" title="如何监控到属性修改并触发警告"></a>如何监控到属性修改并触发警告</h3><ul>
<li>因为 Vue 是单向数据流，易于检测数据的流动，出现了错误可以更加迅速的定位到错误发生的位置。</li>
<li>通过 setter 属性进行检测，修改值将会触发 setter，从而触发警告。</li>
</ul>
<h3 id="v-for-时给元素绑定事件要事件代理吗"><a href="#v-for-时给元素绑定事件要事件代理吗" class="headerlink" title="v-for 时给元素绑定事件要事件代理吗"></a>v-for 时给元素绑定事件要事件代理吗</h3><blockquote>
<p>v-for 中使用事件代理可以使监听器数量和内存占用率都减少，vue 内部并不会自动做事件代理，所以在 v-for 上使用事件代理在性能上会更优。</p>
</blockquote>
<h3 id="父子组件生命周期的执行顺序"><a href="#父子组件生命周期的执行顺序" class="headerlink" title="父子组件生命周期的执行顺序"></a>父子组件生命周期的执行顺序</h3><blockquote>
<p>vue 生命周期：beforeCreate、created、beforeMount、Mounted、beforeUpdate、updated、beforedestroy、destroyed。</p>
</blockquote>
<ul>
<li><strong>加载渲染过程</strong>：父 beforeCreate -&gt; 父 created -&gt; 父 beforeMount -&gt; 子 beforeCreate -&gt; 子 created -&gt; 子 beforeMount -&gt; 子 mounted -&gt; 父 mounted。</li>
<li><strong>子组件更新过程</strong>：父 beforeUpdate -&gt; 子 beforeUpdate -&gt; 子 updated -&gt; 父 updated。</li>
<li><strong>父组件更新过程</strong>：父 beforeUpdate -&gt; 父 updated。</li>
<li><strong>销毁过程</strong>：父 beforeDestroy -&gt; 子 beforeDestroy -&gt; 子 destroyed -&gt; 父 destroyed。</li>
</ul>
<h3 id="NextTick"><a href="#NextTick" class="headerlink" title="NextTick"></a>NextTick</h3><blockquote>
<p>在下次 DOM 更新循环结束之后执行延迟回调，在修改数据之后使用 $nextTick，则可以在回调中获取更新后的 DOM。</p>
</blockquote>
<h3 id="组件-key"><a href="#组件-key" class="headerlink" title="组件 key"></a>组件 key</h3><ul>
<li>Key 是用于追踪哪些列表中的元素被修改、被添加或被移除的辅助标识，开发时需要保证元素的 key 在其同级元素中具有唯一性。</li>
<li>vue、react 都是通过 diff 算法来对比新旧虚拟节点，从而实现更新。Key 值则用来判断该元素是新创建的还是被移动而来的元素，从而减少不必要的重复渲染。</li>
</ul>
<h3 id="组件-data-必须是函数"><a href="#组件-data-必须是函数" class="headerlink" title="组件 data 必须是函数"></a>组件 data 必须是函数</h3><blockquote>
<p>因为 JS 本身的特性带来的，如果 data 是一个对象，那么由于对象本身属于引用类型，当我们修改其中的一个属性时，会影响到所有 Vue 实例的数据。如果将 data 作为一个返回一个对象的函数，那么每一个实例的 data 属性都是独立的，不会相互影响了。</p>
</blockquote>
<h3 id="vuex-全局挂载"><a href="#vuex-全局挂载" class="headerlink" title="vuex 全局挂载"></a>vuex 全局挂载</h3><ul>
<li><strong>window 挂载</strong>：相当于增加全局属性，容易造成变量污染。数据是静态的而只能通过手动更新，数据更新后相关组件也不会重新渲染，必须手动渲染。</li>
<li><strong>vue 实例挂载</strong>：store 数据更新后就会立即渲染所有使用 store 数据的组件。Vuex 使用单向数据流，store 数据的更新需要经过 action 层、mutation 层，层次划分明确，便于管理。</li>
</ul>
<h3 id="Vuex-mutation、Redux-reducer-不能异步"><a href="#Vuex-mutation、Redux-reducer-不能异步" class="headerlink" title="Vuex mutation、Redux reducer 不能异步"></a>Vuex mutation、Redux reducer 不能异步</h3><blockquote>
<p>纯函数，给定同样的输入返回同样的输出，可预测性。</p>
</blockquote>
<h3 id="performance-性能模式"><a href="#performance-性能模式" class="headerlink" title="performance 性能模式"></a>performance 性能模式</h3><blockquote>
<p>通过 Performance API 可以获取到当前页面中与性能相关的信息，Performance.timing 对象包含了各种与浏览器处理相关的时间数据 (接口耗时、资源加载时间等)。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.js：适用于开发模式和支持 performance.mark 的浏览器，开发工具的性能/时间线面板展示。</span></span><br><span class="line"><span class="keyword">const</span> isDev = process.<span class="property">env</span>.<span class="property">NODE_ENV</span> !== <span class="string">&quot;production&quot;</span>;</span><br><span class="line"><span class="title class_">Vue</span>.<span class="property">config</span>.<span class="property">performance</span> = isDev;</span><br></pre></td></tr></table></figure>

<h2 id="React-1"><a href="#React-1" class="headerlink" title="React"></a>React</h2><h3 id="redux-reducer-为何设计成纯函数"><a href="#redux-reducer-为何设计成纯函数" class="headerlink" title="redux reducer 为何设计成纯函数"></a>redux reducer 为何设计成纯函数</h3><blockquote>
<p>redux 的设计思想是不产生副作用、数据更改的状态可回溯。</p>
</blockquote>
<h3 id="react-router-里的标签和普通标签的区别"><a href="#react-router-里的标签和普通标签的区别" class="headerlink" title="react-router 里的标签和普通标签的区别"></a>react-router 里的标签和普通标签的区别</h3><ul>
<li>有 onClick 则执行 OnClick。</li>
<li>阻止 a 标签默认事件（跳转页面）。</li>
<li>使用 history&#x2F;hash 跳转，只是链接发现改变而并没有刷新页面。</li>
</ul>
<h3 id="组件的生命周期"><a href="#组件的生命周期" class="headerlink" title="组件的生命周期"></a>组件的生命周期</h3>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1、组件挂载</span></span><br><span class="line">constructor   <span class="comment">// 实例化：初始化 state，本地化 props，给事件处理函数绑定 this</span></span><br><span class="line"><span class="keyword">static</span> getDerivedStateFromProps  <span class="comment">// 实例化时或 props 变化时调用，返回 新state/null</span></span><br><span class="line">render        <span class="comment">// 渲染函数：不能省略并且必须有返回值 (返回 null/false 表示不渲染)</span></span><br><span class="line">componentDidMount  <span class="comment">// 挂载完成函数：axios 请求、事件绑定、setState 数据、操作 dom</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、组件更新</span></span><br><span class="line"><span class="keyword">static</span> getDeriverdStateFromProps  <span class="comment">// 从 props 中获取 state</span></span><br><span class="line">shouldComponentUpdate    <span class="comment">// 返回 true/false 表示是否更新组件，常用于组件性能优化</span></span><br><span class="line">render                   <span class="comment">// 渲染</span></span><br><span class="line">getSnapshotBeforeUpdate  <span class="comment">// 获取快照：最新渲染输出（提交到 DOM 节点）前被调用</span></span><br><span class="line">componentDidUpdate       <span class="comment">// 更新完成函数</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、组件卸载</span></span><br><span class="line">componentWillUnmount     <span class="comment">// 预销毁函数：移除定时器、事件绑定等</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 4、错误处理</span></span><br><span class="line"><span class="keyword">static</span> getDerivedStateFromError <span class="comment">// 从错误中获取 state</span></span><br><span class="line">componentDidCatch        <span class="comment">// 捕获错误并进行处理</span></span><br></pre></td></tr></table></figure>


<h3 id="Mixin、HOC、Render-Prop、React-Hooks"><a href="#Mixin、HOC、Render-Prop、React-Hooks" class="headerlink" title="Mixin、HOC、Render Prop、React Hooks"></a>Mixin、HOC、Render Prop、React Hooks</h3><h4 id="Mixin"><a href="#Mixin" class="headerlink" title="Mixin"></a>Mixin</h4><blockquote>
<p>缺陷如下：</p>
</blockquote>
<ul>
<li>命名冲突：多个 Mixin 可能定义了相同的 state 字段而导致数据覆盖问题。</li>
<li>相关依赖：组件与 Mixin、多个 Mixin 之间都可能存在依赖关系，维护成本较高。</li>
<li>增加复杂性：一个组件引入过多 mixin 时，代码逻辑将会非常复杂，过多的状态也降低了应用的可预测性。</li>
</ul>
<h4 id="HOC"><a href="#HOC" class="headerlink" title="HOC"></a>HOC</h4><ul>
<li>优势<ul>
<li>HOC 不会影响组件内部的状态，不存在冲突和互相干扰，这就降低了耦合度。</li>
<li>不同于 Mixin 的打平+合并，HOC 具有层级结构（组件树结构），降低了复杂度。</li>
</ul>
</li>
<li>缺陷<ul>
<li>嵌套地狱：每一次 HOC 调用都会产生一个组件实例，过多的嵌套会导致难以溯源，而且可能会存在 props 属性覆盖问题。</li>
<li>静态构建：HOC 只是声明了新组件但不会马上渲染，只有在组件被渲染时才执行。</li>
</ul>
</li>
</ul>
<h4 id="Render-Prop"><a href="#Render-Prop" class="headerlink" title="Render Prop"></a>Render Prop</h4><ul>
<li>优势<ul>
<li>动态构建，组件会重新渲染。</li>
<li>不用担心 props 的命名冲突。</li>
<li>可以溯源，子组件的 props 一定是来自于直接父组件。</li>
</ul>
</li>
<li>缺陷<ul>
<li>嵌套地狱：虽然摆脱了组件多层嵌套的问题，但是转化为了函数回调的嵌套。</li>
<li>使用繁琐：HOC 可以通过装饰器语法的一行代码实现复用，Render Props 则不行。</li>
<li>没有组件的上下文：没有 this.props 属性，不能像 HOC 那样可以直接获取到子组件实例对象 this.props.children。</li>
</ul>
</li>
</ul>
<h4 id="React-Hooks"><a href="#React-Hooks" class="headerlink" title="React Hooks"></a>React Hooks</h4><ul>
<li>优势<ul>
<li>解决了以上的嵌套问题，而且实现了视图和状态的分离，Hooks 还可以相互组合。</li>
<li>Hooks 为函数组件而生，从而解决了类组件的几大问题：this 指向容易错误、声明周期中的逻辑代码难以理解和维护、代码复用成本高等。</li>
</ul>
</li>
<li>缺陷<ul>
<li>存在不能出现在条件、循环中等写法限制，内部实现也不直观，增加了学习成本。</li>
<li>在闭包场景可能会引用到旧的 state、props 值，React.memo 也不能完全替代 shouldComponentUpdate（因为拿不到 state change，只针对 props change）。</li>
</ul>
</li>
</ul>
<h3 id="Flux-思想"><a href="#Flux-思想" class="headerlink" title="Flux 思想"></a>Flux 思想</h3><blockquote>
<p>主要特点就是数据单向流动，具体流程如下：</p>
</blockquote>
<ol>
<li>用户访问 View。</li>
<li>View 发出用户的 Action。</li>
<li>Dispatcher 收到 Action，要求 Store 进行对应的更新。</li>
<li>Store 更新后，发出一个 change 事件。</li>
<li>View 收到 change 后，更新页面。</li>
</ol>
<h3 id="合成事件"><a href="#合成事件" class="headerlink" title="合成事件"></a>合成事件</h3><blockquote>
<p>React SyntheticEvent 中间层通过事件委托的方式基于原生 DOM 事件封装并暴露接口的事件对象，优化了浏览器兼容和性能等问题，</p>
</blockquote>
<ul>
<li>当用户在为 onClick 添加函数时，React 并没有将 Click 时间绑定到 DOM，而是在 document 处监听所有支持的事件。</li>
<li>当事件发生并冒泡至 document 时，React 才会让中间层 SyntheticEvent 将所有事件合成。所以原生事件会先执行，然后执行 React 合成事件，最后执行真正在 document 上挂载的事件。</li>
<li>React 事件和原生事件最好不要混用。原生事件中如果执行了 stopPropagation 方法，就会导致其他 React 事件失效。因为所有元素的事件将无法冒泡到 document上，导致所有的 React事件都将无法被触发。</li>
</ul>
<h3 id="setState-是异步还是同步"><a href="#setState-是异步还是同步" class="headerlink" title="setState 是异步还是同步"></a>setState 是异步还是同步</h3><ul>
<li>setState 只在合成事件和钩子函数中是异步的，在原生事件和 setTimeout 中都是同步的。</li>
<li>setState 的异步并不是说内部由异步代码实现，其实本身执行的过程和代码都是同步的，只是合成事件和钩子函数的调用顺序在更新之前，导致在合成事件和钩子函数中无法马上获取更新后的值，形成了所谓的“异步”。但可以通过第二个参数 callback 获取最新数据。<br>  setState 的批量更新优化也是建立在“异步”（合成事件、钩子函数）之上的，在原生事件和 setTimeout 中不会批量更新，在“异步”中如果对同一个值进行多次 setState，setState的批量更新策略会对其进行覆盖，取最后一次的执行，如果是同时 setState 多个不同的值，在更新时会对其进行合并批量更新。</li>
</ul>
<h3 id="redux、dva、vuex"><a href="#redux、dva、vuex" class="headerlink" title="redux、dva、vuex"></a>redux、dva、vuex</h3><ul>
<li>redux：通过 store 存储，通过 dispatch(action) 唯一更改，reducer 描述如何更改。</li>
<li>dva：基于 redux，结合 redux-saga 等中间件进行封装。</li>
<li>vuex：类似dva，集成化。action 异步，mutation 同步。</li>
</ul>
<h3 id="redux-中间件"><a href="#redux-中间件" class="headerlink" title="redux 中间件"></a>redux 中间件</h3><blockquote>
<p>中间件提供第三方插件的模式，自定义拦截 action -&gt; reducer 的过程。变为 action -&gt; middlewares -&gt; reducer。这种机制可以让我们改变数据流，实现异步 action、action 过滤、日志输出、异常报告等功能。常见的中间件如下：</p>
</blockquote>
<ul>
<li><strong>redux-thunk</strong>：处理异步操作。</li>
<li><strong>redux-logger</strong>：提供日志输出。</li>
<li><strong>redux-promise</strong>：处理异步操作，actionCreator 的返回值是 promise。</li>
</ul>
<h3 id="redux-缺点"><a href="#redux-缺点" class="headerlink" title="redux 缺点"></a>redux 缺点</h3><ul>
<li>组件所需要的数据必须由父组件传过来，而不能像 flux 中直接从 store 获取。</li>
<li>组件相关数据更新时，父组件即使用不到该组件也会重新 render，这样可能会影响效率，或者需要写复杂的 shouldComponentUpdate 进行判断。</li>
</ul>
<h3 id="性能优化方案"><a href="#性能优化方案" class="headerlink" title="性能优化方案"></a>性能优化方案</h3><ul>
<li>使用 production 版本的 react.js。</li>
<li>重写 shouldComponentUpdate 来避免不必要的 dom 操作。</li>
<li>使用 key 来帮助 React 识别列表中所有子组件的最小变化。</li>
</ul>
<h3 id="setState-执行"><a href="#setState-执行" class="headerlink" title="setState 执行"></a>setState 执行</h3><ul>
<li>前两次都是在 react 自身声明周期内，触发时 <code>isBatchingUpdates: true</code>，所以并不会直接执行更新，而是加入了 dirtyComponents，所以获取的都是更新前的状态 0。</li>
<li>两次 setState 相同，react 内部会合并而只执行一次，完成后 state.val 值为 1。</li>
<li>setTimeout 中的代码触发时 <code>isBatchingUpdate: false</code>，直接更新而输出 2、3。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 0、0、2、3</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Example</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>();</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">state</span> = &#123; <span class="attr">val</span>: <span class="number">0</span> &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  </span><br><span class="line">    <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123;<span class="attr">val</span>: <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">val</span> + <span class="number">1</span>&#125;);</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">val</span>);</span><br><span class="line"></span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123;<span class="attr">val</span>: <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">val</span> + <span class="number">1</span>&#125;);</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">val</span>);</span><br><span class="line"></span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123;<span class="attr">val</span>: <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">val</span> + <span class="number">1</span>&#125;);</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">val</span>);</span><br><span class="line"></span><br><span class="line">            <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123;<span class="attr">val</span>: <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">val</span> + <span class="number">1</span>&#125;);</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">val</span>);</span><br><span class="line">        &#125;, <span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h1 id="四、小程序"><a href="#四、小程序" class="headerlink" title="四、小程序"></a>四、小程序</h1><h2 id="架构原理"><a href="#架构原理" class="headerlink" title="架构原理"></a>架构原理</h2><ul>
<li>数据驱动的架构模式，UI 和数据是分离的，所有的页面更新都通过对更新数据来实现。</li>
<li>小程序本质是一个单页面应用，所有的页面渲染和事件处理都在一个页面内进行，但又可以通过微信客户端调用原生的各种接口。</li>
<li>它从技术讲和现有的前端开发差不多，采用 JS、WXML、WXSS 三种技术进行开发。功能可分为 webview、appService 两个部分。webview 用来展现 UI，appService 用来处理业务逻辑、数据及接口调用。两个部分在两个进程中运行，通过系统层 JSBridge 实现通信、UI 渲染、事件处理等。</li>
</ul>
<h2 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h2><ul>
<li>**onLoad()**：页面加载时触发，只会调用一次，可获取当前页面路径中的参数。</li>
<li>**onShow()**：页面显示&#x2F;切入前台时触发，一般用来发送数据请求。</li>
<li>**onReady()**：页面初次渲染完成时触发, 只会调用一次，代表页面已可和视图层进行交互。</li>
<li>**onHide()**：页面隐藏&#x2F;切入后台时触发, 如底部 tab 切换到其他页面或小程序切入后台等。</li>
<li>**onUnload()**：页面卸载时触发，比如 redirectTo、navigateBack 到其他页面时。</li>
</ul>
<h2 id="双向绑定对比-vue"><a href="#双向绑定对比-vue" class="headerlink" title="双向绑定对比 vue"></a>双向绑定对比 vue</h2><blockquote>
<p>大体相同，但小程序直接 this.data 的属性不可以同步到视图，必须调用 this.setData() 方法。</p>
</blockquote>
<h2 id="wxml-与标准-html"><a href="#wxml-与标准-html" class="headerlink" title="wxml 与标准 html"></a>wxml 与标准 html</h2><blockquote>
<p>wxml 基于 xml 设计，标签只能在微信小程序中使用，不能使用 html 标签。</p>
</blockquote>
<h2 id="页面间传递数据"><a href="#页面间传递数据" class="headerlink" title="页面间传递数据"></a>页面间传递数据</h2><ul>
<li>使用全局变量实现数据传递。</li>
<li>页面跳转或重定向时，使用 url 带参数传递数据。</li>
<li>使用组件模板 template 传递参数。</li>
<li>使用缓存传递参数。</li>
<li>使用数据库传递数据。</li>
</ul>
<h2 id="提高应用速度"><a href="#提高应用速度" class="headerlink" title="提高应用速度"></a>提高应用速度</h2><ul>
<li>提高页面加载速度</li>
<li>用户行为预测</li>
<li>减少默认 data 的大小</li>
<li>组件化方案</li>
</ul>
<h1 id="五、编程相关"><a href="#五、编程相关" class="headerlink" title="五、编程相关"></a>五、编程相关</h1><h2 id="执行结果"><a href="#执行结果" class="headerlink" title="执行结果"></a>执行结果</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 结果：[1, NaN, NaN]</span></span><br><span class="line"><span class="comment">// 原因：map 回调传入 item、index，执行 parseInt(1, 0)、parseInt(2, 1)、parseInt(3, 2)。</span></span><br><span class="line">[<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;3&#x27;</span>].<span class="title function_">map</span>(<span class="built_in">parseInt</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 什么情况下会打印 1</span></span><br><span class="line"><span class="keyword">var</span> a = ?;</span><br><span class="line"><span class="keyword">if</span>(a == <span class="number">1</span> &amp;&amp; a == <span class="number">2</span> &amp;&amp; a == <span class="number">3</span>)&#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> a = &#123;</span><br><span class="line">  <span class="attr">value</span>: <span class="number">0</span>,</span><br><span class="line">  <span class="title function_">valueOf</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> ++<span class="variable language_">this</span>.<span class="property">value</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 实现 (5).add(3).minus(2)</span></span><br><span class="line"><span class="title class_">Number</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">add</span> = <span class="keyword">function</span>(<span class="params">n</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="variable language_">this</span> + n;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Number</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">minus</span> = <span class="keyword">function</span>(<span class="params">n</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="variable language_">this</span> - n;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 某公司 1-12 月的销售额为：&#123;1:22, 2:12, 5: 88&#125;，请处理为：</span></span><br><span class="line"><span class="comment">// [22, 12, null, null, 88, null, null, null, null, null, null, null]</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">convert</span>(<span class="params">obj</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Array</span>.<span class="title function_">from</span>(&#123; <span class="attr">length</span>: <span class="number">12</span> &#125;).<span class="title function_">map</span>(<span class="function">(<span class="params">item, i</span>) =&gt;</span> obj[i] || <span class="literal">null</span>).<span class="title function_">slice</span>(<span class="number">1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="综合考察"><a href="#综合考察" class="headerlink" title="综合考察"></a>综合考察</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Foo</span>(<span class="params"></span>) &#123;</span><br><span class="line">  getName = <span class="keyword">function</span> (<span class="params"></span>) &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">1</span>); &#125;;</span><br><span class="line">  <span class="keyword">return</span> <span class="variable language_">this</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Foo</span>.<span class="property">getName</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">2</span>);&#125;;</span><br><span class="line"><span class="title class_">Foo</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">getName</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">3</span>);&#125;;</span><br><span class="line"><span class="keyword">var</span> getName = <span class="keyword">function</span> (<span class="params"></span>) &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">4</span>);&#125;;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getName</span>(<span class="params"></span>) &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">5</span>);&#125;</span><br><span class="line"></span><br><span class="line"><span class="title class_">Foo</span>.<span class="title function_">getName</span>();        <span class="comment">// 2</span></span><br><span class="line"><span class="title function_">getName</span>();            <span class="comment">// 4</span></span><br><span class="line"><span class="title class_">Foo</span>().<span class="title function_">getName</span>();      <span class="comment">// 1</span></span><br><span class="line"><span class="title function_">getName</span>();            <span class="comment">// 1</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Foo</span>.<span class="title function_">getName</span>();    <span class="comment">// 2</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Foo</span>().<span class="title function_">getName</span>();  <span class="comment">// 3</span></span><br><span class="line"><span class="keyword">new</span> <span class="keyword">new</span> <span class="title class_">Foo</span>().<span class="title function_">getName</span>();    <span class="comment">// 3</span></span><br></pre></td></tr></table></figure>



<h2 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* <span class="doctag">@desp</span> 变量提升：JS 解析器都会将函数体内声明的变量移到函数体的顶部。</span></span><br><span class="line"><span class="comment">* <span class="doctag">@result</span> ：Goodbye Jack、World</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">var</span> name = <span class="string">&#x27;World&#x27;</span>;</span><br><span class="line">(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">  <span class="comment">// var name; </span></span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">typeof</span> name === <span class="string">&#x27;undefined&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">var</span> name = <span class="string">&#x27;Jack&#x27;</span>;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Goodbye &#x27;</span> + name);</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Hello &#x27;</span> + name);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)();</span><br><span class="line">(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 查找变量时，当前函数体内没找到则到一直向上到全局对象中寻找。</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(name)</span><br><span class="line">&#125;)();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 赋值表达式：undefined、&#123; n: 2 &#125;</span></span><br><span class="line"><span class="keyword">var</span> a = &#123;<span class="attr">n</span>: <span class="number">1</span>&#125;;</span><br><span class="line"><span class="keyword">var</span> b = a;</span><br><span class="line">a.<span class="property">x</span> = a = &#123;<span class="attr">n</span>: <span class="number">2</span>&#125;;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(a.<span class="property">x</span>, b.<span class="property">x</span>)</span><br></pre></td></tr></table></figure>

<h2 id="作用域"><a href="#作用域" class="headerlink" title="作用域"></a>作用域</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> b = <span class="number">10</span>;</span><br><span class="line">(<span class="keyword">function</span> <span class="title function_">b</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="comment">// 内部作用域会先去查找已有变量的声明，有则赋值，但 IIFE 函数无法赋值。</span></span><br><span class="line">    b = <span class="number">20</span>;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(b);         <span class="comment">// [Function b]</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">window</span>.<span class="property">b</span>);  <span class="comment">// 10</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// window.b = 20 打印：[Function b]、20</span></span><br><span class="line">    <span class="comment">// var b = 20 打印：20、10</span></span><br><span class="line">&#125;)();</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> a = <span class="number">10</span>;</span><br><span class="line">(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(a)   <span class="comment">// undefined</span></span><br><span class="line">    a = <span class="number">5</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">window</span>.<span class="property">a</span>)   <span class="comment">// 10</span></span><br><span class="line">    <span class="keyword">var</span> a = <span class="number">20</span>;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(a)   <span class="comment">// 20</span></span><br><span class="line">&#125;)();</span><br></pre></td></tr></table></figure>


<h2 id="this-指针"><a href="#this-指针" class="headerlink" title="this 指针"></a>this 指针</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 4 2 1</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Foo</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="title class_">Foo</span>.<span class="property">a</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">1</span>)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="variable language_">this</span>.<span class="property">a</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">2</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Foo</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">a</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">3</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Foo</span>.<span class="property">a</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">4</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Foo</span>.<span class="title function_">a</span>();</span><br><span class="line"><span class="keyword">let</span> obj = <span class="keyword">new</span> <span class="title class_">Foo</span>(); </span><br><span class="line">obj.<span class="title function_">a</span>();</span><br><span class="line"><span class="title class_">Foo</span>.<span class="title function_">a</span>();</span><br></pre></td></tr></table></figure>

<h2 id="对象应用"><a href="#对象应用" class="headerlink" title="对象应用"></a>对象应用</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// http://www.baidu.com</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">changeObjProperty</span>(<span class="params">o</span>) &#123;</span><br><span class="line">  o.<span class="property">siteUrl</span> = <span class="string">&quot;http://www.baidu.com&quot;</span></span><br><span class="line">  o = <span class="keyword">new</span> <span class="title class_">Object</span>()</span><br><span class="line">  o.<span class="property">siteUrl</span> = <span class="string">&quot;http://www.google.com&quot;</span></span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">let</span> webSite = <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line"><span class="title function_">changeObjProperty</span>(webSite);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(webSite.<span class="property">siteUrl</span>); </span><br><span class="line"></span><br><span class="line"><span class="comment">// [ , , 1, 2]</span></span><br><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    <span class="string">&#x27;2&#x27;</span>: <span class="number">3</span>,</span><br><span class="line">    <span class="string">&#x27;3&#x27;</span>: <span class="number">4</span>,</span><br><span class="line">    <span class="string">&#x27;length&#x27;</span>: <span class="number">2</span>,</span><br><span class="line">    <span class="string">&#x27;splice&#x27;</span>: <span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">splice</span>,</span><br><span class="line">    <span class="string">&#x27;push&#x27;</span>: <span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">push</span></span><br><span class="line">&#125;</span><br><span class="line">obj.<span class="title function_">push</span>(<span class="number">1</span>)</span><br><span class="line">obj.<span class="title function_">push</span>(<span class="number">2</span>)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(obj)</span><br></pre></td></tr></table></figure>


<h2 id="事件循环-x2F-异步"><a href="#事件循环-x2F-异步" class="headerlink" title="事件循环&#x2F;异步"></a>事件循环&#x2F;异步</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// script start、async1 start、async2、promise1、</span></span><br><span class="line"><span class="comment">// script end、async1 end、promise2、setTimeout</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">async1</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;async1 start&#x27;</span>);</span><br><span class="line">    <span class="keyword">await</span> <span class="title function_">async2</span>();</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;async1 end&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">async2</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;async2&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;script start&#x27;</span>);</span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;setTimeout&#x27;</span>);</span><br><span class="line">&#125;, <span class="number">0</span>)</span><br><span class="line"><span class="title function_">async1</span>();</span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="keyword">function</span>(<span class="params">resolve</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;promise1&#x27;</span>);</span><br><span class="line">    <span class="title function_">resolve</span>();</span><br><span class="line">&#125;).<span class="title function_">then</span>(<span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;promise2&#x27;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;script end&#x27;</span>);</span><br></pre></td></tr></table></figure>


<h2 id="jsonp-封装"><a href="#jsonp-封装" class="headerlink" title="jsonp 封装"></a>jsonp 封装</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">jsonp</span> (&#123;url, param, callback&#125;) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">var</span> script = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;script&#x27;</span>)</span><br><span class="line">    <span class="variable language_">window</span>.<span class="property">callback</span> = <span class="keyword">function</span> (<span class="params">data</span>) &#123;</span><br><span class="line">      <span class="title function_">resolve</span>(data)</span><br><span class="line">      <span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">removeChild</span>(<span class="string">&#x27;script&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">var</span> param = &#123;...param, callback&#125;</span><br><span class="line">    <span class="keyword">var</span> arr = []</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> param) &#123;</span><br><span class="line">      arr.<span class="title function_">push</span>(<span class="string">`<span class="subst">$&#123;key&#125;</span>=<span class="subst">$&#123;param[key]&#125;</span>`</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    script.<span class="property">src</span> = <span class="string">`<span class="subst">$&#123;url&#125;</span>?<span class="subst">$&#123;arr.join(<span class="string">&#x27;&amp;&#x27;</span>)&#125;</span>`</span></span><br><span class="line">    <span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(script)</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="实现一个函数-sleep"><a href="#实现一个函数-sleep" class="headerlink" title="实现一个函数 sleep"></a>实现一个函数 sleep</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Promise</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">sleep1</span>(<span class="params">time</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function"><span class="params">resolve</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">      <span class="title function_">resolve</span>();</span><br><span class="line">    &#125;, time);</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">sleep1</span>(<span class="number">1000</span>).<span class="title function_">then</span>(<span class="function">() =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;sleep1&quot;</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">// Generator</span></span><br><span class="line"><span class="keyword">function</span>* <span class="title function_">sleep2</span>(<span class="params">time</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">yield</span> <span class="title function_">sleep1</span>(time);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> s = <span class="title function_">sleep2</span>(<span class="number">1500</span>);</span><br><span class="line">s.<span class="title function_">next</span>().<span class="property">value</span>.<span class="title function_">then</span>(<span class="function">() =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;sleep2&quot;</span>));</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// Async/Await</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">sleep3</span>(<span class="params">time</span>) &#123;</span><br><span class="line">  <span class="keyword">await</span> <span class="title function_">sleep1</span>(time);</span><br><span class="line">&#125;</span><br><span class="line">(<span class="keyword">async</span> () =&gt; &#123;</span><br><span class="line">  <span class="keyword">await</span> <span class="title function_">sleep3</span>(<span class="number">2000</span>);</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;sleep3&quot;</span>)</span><br><span class="line">&#125;)()</span><br></pre></td></tr></table></figure>


<h2 id="消息队列的类实现"><a href="#消息队列的类实现" class="headerlink" title="消息队列的类实现"></a>消息队列的类实现</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 设计一个 LazyMan 类，实现以下功能</span></span><br><span class="line"><span class="title class_">LazyMan</span>(<span class="string">&#x27;Tony&#x27;</span>);</span><br><span class="line"><span class="comment">// Hi I am Tony</span></span><br><span class="line"><span class="title class_">LazyMan</span>(<span class="string">&#x27;Tony&#x27;</span>).<span class="title function_">sleep</span>(<span class="number">10</span>).<span class="title function_">eat</span>(<span class="string">&#x27;lunch&#x27;</span>);</span><br><span class="line"><span class="comment">// Hi I am Tony</span></span><br><span class="line"><span class="comment">// 等待了10秒...</span></span><br><span class="line"><span class="comment">// I am eating lunch</span></span><br><span class="line"><span class="title class_">LazyMan</span>(<span class="string">&#x27;Tony&#x27;</span>).<span class="title function_">eat</span>(<span class="string">&#x27;lunch&#x27;</span>).<span class="title function_">sleep</span>(<span class="number">10</span>).<span class="title function_">eat</span>(<span class="string">&#x27;dinner&#x27;</span>);</span><br><span class="line"><span class="comment">// Hi I am Tony</span></span><br><span class="line"><span class="comment">// I am eating lunch</span></span><br><span class="line"><span class="comment">// 等待了10秒...</span></span><br><span class="line"><span class="comment">// I am eating diner</span></span><br><span class="line"><span class="title class_">LazyMan</span>(<span class="string">&#x27;Tony&#x27;</span>).<span class="title function_">eat</span>(<span class="string">&#x27;lunch&#x27;</span>).<span class="title function_">eat</span>(<span class="string">&#x27;dinner&#x27;</span>).<span class="title function_">sleepF</span>(<span class="number">5</span>)</span><br><span class="line">.<span class="title function_">sleep</span>(<span class="number">10</span>).<span class="title function_">eat</span>(<span class="string">&#x27;food&#x27;</span>);</span><br><span class="line"><span class="comment">// Hi I am Tony</span></span><br><span class="line"><span class="comment">// 等待了5秒...</span></span><br><span class="line"><span class="comment">// I am eating lunch</span></span><br><span class="line"><span class="comment">// I am eating dinner</span></span><br><span class="line"><span class="comment">// 等待了10秒...</span></span><br><span class="line"><span class="comment">// I am eating food</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">LazyManClass</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">fns</span> = [];</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`Hi I am <span class="subst">$&#123;<span class="variable language_">this</span>.name&#125;</span>`</span>);</span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="title function_">next</span>();</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">sleep</span>(<span class="params">time</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> <span class="title function_">fn</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">            <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">                <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`等待了<span class="subst">$&#123;time&#125;</span>秒...`</span>)</span><br><span class="line">                <span class="variable language_">this</span>.<span class="title function_">next</span>();</span><br><span class="line">            &#125;, time * <span class="number">1000</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">fns</span>.<span class="title function_">push</span>(fn);</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">sleepF</span>(<span class="params">time</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> <span class="title function_">fn</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">            <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">                <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`等待了<span class="subst">$&#123;time&#125;</span>秒...`</span>)</span><br><span class="line">                <span class="variable language_">this</span>.<span class="title function_">next</span>();</span><br><span class="line">            &#125;, time * <span class="number">1000</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">fns</span>.<span class="title function_">unshift</span>(fn);</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">eat</span>(<span class="params">food</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> <span class="title function_">fn</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`I am eating <span class="subst">$&#123;food&#125;</span>`</span>);</span><br><span class="line">            <span class="variable language_">this</span>.<span class="title function_">next</span>();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">fns</span>.<span class="title function_">push</span>(fn);</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">next</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> fn = <span class="variable language_">this</span>.<span class="property">fns</span>.<span class="title function_">shift</span>();</span><br><span class="line">        fn &amp;&amp; <span class="title function_">fn</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">LazyMan</span> = (<span class="params">name</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">LazyManClass</span>(name);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>








    </div>

    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;margin-top:20px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>chuangges
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://chuangges.gitee.io/2020/03/22/12-%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B9%8B%E5%9F%BA%E7%A1%80%E7%AF%87/" title="面试题之基础篇">https://chuangges.gitee.io/2020/03/22/12-面试题之基础篇/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/zh_CN" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2019/11/06/11-2-typescript%20%E8%BF%9B%E9%98%B6%E8%AF%AD%E6%B3%95/" rel="prev" title="TypeScript 进阶语法">
      <i class="fa fa-chevron-left"></i> TypeScript 进阶语法
    </a></div>
      <div class="post-nav-item">
    <a href="/2020/04/05/13-%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B9%8B%E6%8F%90%E5%8D%87%E7%AF%87/" rel="next" title="面试题之提升篇">
      面试题之提升篇 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81HTML%E3%80%81CSS"><span class="nav-number">1.</span> <span class="nav-text">一、HTML、CSS</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#link%E3%80%81-import-%E5%AF%BC%E5%85%A5"><span class="nav-number">1.1.</span> <span class="nav-text">link、@import 导入</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#HTML5-form-%E8%87%AA%E5%8A%A8%E5%AE%8C%E6%88%90"><span class="nav-number">1.2.</span> <span class="nav-text">HTML5 form 自动完成</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B5%8F%E8%A7%88%E5%99%A8%E6%B8%B2%E6%9F%93"><span class="nav-number">1.3.</span> <span class="nav-text">浏览器渲染</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B5%8F%E8%A7%88%E5%99%A8%E9%80%9A%E4%BF%A1"><span class="nav-number">1.4.</span> <span class="nav-text">浏览器通信</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B5%8F%E8%A7%88%E5%99%A8%E7%BC%93%E5%AD%98"><span class="nav-number">1.5.</span> <span class="nav-text">浏览器缓存</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#CSRF-%E6%94%BB%E5%87%BB"><span class="nav-number">1.6.</span> <span class="nav-text">CSRF 攻击</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#CSP-%E5%86%85%E5%AE%B9%E5%AE%89%E5%85%A8%E7%AD%96%E7%95%A5"><span class="nav-number">1.7.</span> <span class="nav-text">CSP 内容安全策略</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#PWA-%E6%B8%90%E8%BF%9B%E5%BC%8F%E7%BD%91%E9%A1%B5%E5%BA%94%E7%94%A8"><span class="nav-number">1.8.</span> <span class="nav-text">PWA 渐进式网页应用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#HTTPS-%E8%AE%A9%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93%E6%9B%B4%E5%AE%89%E5%85%A8"><span class="nav-number">1.9.</span> <span class="nav-text">HTTPS 让数据传输更安全</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B2%99%E7%9B%92%E9%9A%94%E7%A6%BB%E9%A1%B5%E9%9D%A2%E5%92%8C%E7%B3%BB%E7%BB%9F"><span class="nav-number">1.10.</span> <span class="nav-text">沙盒隔离页面和系统</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%A7%BB%E5%8A%A8%E7%AB%AF%E9%80%82%E9%85%8D%E6%96%B9%E6%A1%88"><span class="nav-number">1.11.</span> <span class="nav-text">移动端适配方案</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#BFC-%E5%8F%8A%E5%85%B6%E5%BA%94%E7%94%A8"><span class="nav-number">1.12.</span> <span class="nav-text">BFC 及其应用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%87%8D%E7%BB%98%E3%80%81%E5%9B%9E%E6%B5%81"><span class="nav-number">1.13.</span> <span class="nav-text">重绘、回流</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Web-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96"><span class="nav-number">1.14.</span> <span class="nav-text">Web 性能优化</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#opacity%E3%80%81visibility%E3%80%81display"><span class="nav-number">1.15.</span> <span class="nav-text">opacity、visibility、display</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Rem-%E5%8F%8A%E5%85%B6%E5%8E%9F%E7%90%86"><span class="nav-number">1.16.</span> <span class="nav-text">Rem 及其原理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%A7%BB%E5%8A%A8%E7%AB%AF%E8%A7%86%E5%8F%A3%E9%85%8D%E7%BD%AE"><span class="nav-number">1.17.</span> <span class="nav-text">移动端视口配置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BC%AA%E7%B1%BB%E5%92%8C%E4%BC%AA%E5%85%83%E7%B4%A0"><span class="nav-number">1.18.</span> <span class="nav-text">伪类和伪元素</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#css-%E5%8F%AF%E7%BB%A7%E6%89%BF%E5%B1%9E%E6%80%A7"><span class="nav-number">1.19.</span> <span class="nav-text">css 可继承属性</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81JS"><span class="nav-number">2.</span> <span class="nav-text">二、JS</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#JS-%E7%BC%96%E8%AF%91"><span class="nav-number">2.1.</span> <span class="nav-text">JS 编译</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%B1%BB%E5%9E%8B%E5%88%A4%E6%96%AD"><span class="nav-number">2.2.</span> <span class="nav-text">类型判断</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%9A%90%E5%BC%8F%E8%BD%AC%E6%8D%A2"><span class="nav-number">2.3.</span> <span class="nav-text">隐式转换</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%B2%BE%E5%BA%A6%E4%B8%A2%E5%A4%B1"><span class="nav-number">2.4.</span> <span class="nav-text">精度丢失</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#if-%E5%88%86%E6%94%AF%E4%BC%98%E5%8C%96"><span class="nav-number">2.5.</span> <span class="nav-text">if 分支优化</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#JS-%E7%BB%A7%E6%89%BF%E6%A8%A1%E5%BC%8F"><span class="nav-number">2.6.</span> <span class="nav-text">JS 继承模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#this-%E6%8C%87%E5%90%91"><span class="nav-number">2.7.</span> <span class="nav-text">this 指向</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%90%84%E7%A7%8D%E4%BD%8D%E7%BD%AE"><span class="nav-number">2.8.</span> <span class="nav-text">各种位置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B9%B3%E6%BB%91%E6%BB%9A%E5%8A%A8"><span class="nav-number">2.9.</span> <span class="nav-text">平滑滚动</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A4%8D%E5%88%B6%E5%8A%9F%E8%83%BD"><span class="nav-number">2.10.</span> <span class="nav-text">复制功能</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%98%B2%E6%8A%96%E5%92%8C%E8%8A%82%E6%B5%81"><span class="nav-number">2.11.</span> <span class="nav-text">防抖和节流</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F"><span class="nav-number">2.12.</span> <span class="nav-text">内存泄漏</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%85%E5%AD%98%E6%9C%BA%E5%88%B6"><span class="nav-number">2.13.</span> <span class="nav-text">内存机制</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A0%86%E6%A0%88%E6%BA%A2%E5%87%BA"><span class="nav-number">2.14.</span> <span class="nav-text">堆栈溢出</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1"><span class="nav-number">2.15.</span> <span class="nav-text">异步任务</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%82%E6%AD%A5%E7%BC%96%E7%A8%8B"><span class="nav-number">2.16.</span> <span class="nav-text">异步编程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7"><span class="nav-number">2.17.</span> <span class="nav-text">构建工具</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A8%A1%E5%9D%97%E5%BE%AA%E7%8E%AF"><span class="nav-number">2.18.</span> <span class="nav-text">模块循环</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#apply%E3%80%81call%E3%80%81bind"><span class="nav-number">2.19.</span> <span class="nav-text">apply、call、bind</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E5%92%8C%E6%99%AE%E9%80%9A%E5%87%BD%E6%95%B0"><span class="nav-number">2.20.</span> <span class="nav-text">箭头函数和普通函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#MVC%E3%80%81MVP%E3%80%81MVVM"><span class="nav-number">2.21.</span> <span class="nav-text">MVC、MVP、MVVM</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Set%E3%80%81Map%E3%80%81WeakSet%E3%80%81WeakMap"><span class="nav-number">2.22.</span> <span class="nav-text">Set、Map、WeakSet、WeakMap</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#webpack-loader%E3%80%81plugin"><span class="nav-number">2.23.</span> <span class="nav-text">webpack loader、plugin</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81JS-%E6%A1%86%E6%9E%B6"><span class="nav-number">3.</span> <span class="nav-text">三、JS 框架</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Angular%E3%80%81React%E3%80%81Vue"><span class="nav-number">3.1.</span> <span class="nav-text">Angular、React、Vue</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8C%BA%E5%88%AB"><span class="nav-number">3.1.1.</span> <span class="nav-text">区别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Vue"><span class="nav-number">3.1.2.</span> <span class="nav-text">Vue</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#React"><span class="nav-number">3.1.3.</span> <span class="nav-text">React</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Angular"><span class="nav-number">3.1.4.</span> <span class="nav-text">Angular</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%96%B0%E6%9C%BA%E5%88%B6"><span class="nav-number">3.1.5.</span> <span class="nav-text">数据更新机制</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Vue-1"><span class="nav-number">3.2.</span> <span class="nav-text">Vue</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81"><span class="nav-number">3.2.1.</span> <span class="nav-text">单向数据流</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A%E6%95%B0%E6%8D%AE"><span class="nav-number">3.2.2.</span> <span class="nav-text">双向绑定数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A%E5%92%8C-vuex-%E6%98%AF%E5%90%A6%E5%86%B2%E7%AA%81"><span class="nav-number">3.2.3.</span> <span class="nav-text">双向绑定和 vuex 是否冲突</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Proxy-%E6%9B%BF%E4%BB%A3-Object-defineProperty"><span class="nav-number">3.2.4.</span> <span class="nav-text">Proxy 替代 Object.defineProperty</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E7%9B%91%E6%8E%A7%E5%88%B0%E5%B1%9E%E6%80%A7%E4%BF%AE%E6%94%B9%E5%B9%B6%E8%A7%A6%E5%8F%91%E8%AD%A6%E5%91%8A"><span class="nav-number">3.2.5.</span> <span class="nav-text">如何监控到属性修改并触发警告</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#v-for-%E6%97%B6%E7%BB%99%E5%85%83%E7%B4%A0%E7%BB%91%E5%AE%9A%E4%BA%8B%E4%BB%B6%E8%A6%81%E4%BA%8B%E4%BB%B6%E4%BB%A3%E7%90%86%E5%90%97"><span class="nav-number">3.2.6.</span> <span class="nav-text">v-for 时给元素绑定事件要事件代理吗</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E7%9A%84%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F"><span class="nav-number">3.2.7.</span> <span class="nav-text">父子组件生命周期的执行顺序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#NextTick"><span class="nav-number">3.2.8.</span> <span class="nav-text">NextTick</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6-key"><span class="nav-number">3.2.9.</span> <span class="nav-text">组件 key</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6-data-%E5%BF%85%E9%A1%BB%E6%98%AF%E5%87%BD%E6%95%B0"><span class="nav-number">3.2.10.</span> <span class="nav-text">组件 data 必须是函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#vuex-%E5%85%A8%E5%B1%80%E6%8C%82%E8%BD%BD"><span class="nav-number">3.2.11.</span> <span class="nav-text">vuex 全局挂载</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Vuex-mutation%E3%80%81Redux-reducer-%E4%B8%8D%E8%83%BD%E5%BC%82%E6%AD%A5"><span class="nav-number">3.2.12.</span> <span class="nav-text">Vuex mutation、Redux reducer 不能异步</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#performance-%E6%80%A7%E8%83%BD%E6%A8%A1%E5%BC%8F"><span class="nav-number">3.2.13.</span> <span class="nav-text">performance 性能模式</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#React-1"><span class="nav-number">3.3.</span> <span class="nav-text">React</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#redux-reducer-%E4%B8%BA%E4%BD%95%E8%AE%BE%E8%AE%A1%E6%88%90%E7%BA%AF%E5%87%BD%E6%95%B0"><span class="nav-number">3.3.1.</span> <span class="nav-text">redux reducer 为何设计成纯函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#react-router-%E9%87%8C%E7%9A%84%E6%A0%87%E7%AD%BE%E5%92%8C%E6%99%AE%E9%80%9A%E6%A0%87%E7%AD%BE%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-number">3.3.2.</span> <span class="nav-text">react-router 里的标签和普通标签的区别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="nav-number">3.3.3.</span> <span class="nav-text">组件的生命周期</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Mixin%E3%80%81HOC%E3%80%81Render-Prop%E3%80%81React-Hooks"><span class="nav-number">3.3.4.</span> <span class="nav-text">Mixin、HOC、Render Prop、React Hooks</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#Mixin"><span class="nav-number">3.3.4.1.</span> <span class="nav-text">Mixin</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#HOC"><span class="nav-number">3.3.4.2.</span> <span class="nav-text">HOC</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Render-Prop"><span class="nav-number">3.3.4.3.</span> <span class="nav-text">Render Prop</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#React-Hooks"><span class="nav-number">3.3.4.4.</span> <span class="nav-text">React Hooks</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Flux-%E6%80%9D%E6%83%B3"><span class="nav-number">3.3.5.</span> <span class="nav-text">Flux 思想</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%88%E6%88%90%E4%BA%8B%E4%BB%B6"><span class="nav-number">3.3.6.</span> <span class="nav-text">合成事件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#setState-%E6%98%AF%E5%BC%82%E6%AD%A5%E8%BF%98%E6%98%AF%E5%90%8C%E6%AD%A5"><span class="nav-number">3.3.7.</span> <span class="nav-text">setState 是异步还是同步</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#redux%E3%80%81dva%E3%80%81vuex"><span class="nav-number">3.3.8.</span> <span class="nav-text">redux、dva、vuex</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#redux-%E4%B8%AD%E9%97%B4%E4%BB%B6"><span class="nav-number">3.3.9.</span> <span class="nav-text">redux 中间件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#redux-%E7%BC%BA%E7%82%B9"><span class="nav-number">3.3.10.</span> <span class="nav-text">redux 缺点</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88"><span class="nav-number">3.3.11.</span> <span class="nav-text">性能优化方案</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#setState-%E6%89%A7%E8%A1%8C"><span class="nav-number">3.3.12.</span> <span class="nav-text">setState 执行</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9B%9B%E3%80%81%E5%B0%8F%E7%A8%8B%E5%BA%8F"><span class="nav-number">4.</span> <span class="nav-text">四、小程序</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9E%B6%E6%9E%84%E5%8E%9F%E7%90%86"><span class="nav-number">4.1.</span> <span class="nav-text">架构原理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="nav-number">4.2.</span> <span class="nav-text">生命周期</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A%E5%AF%B9%E6%AF%94-vue"><span class="nav-number">4.3.</span> <span class="nav-text">双向绑定对比 vue</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#wxml-%E4%B8%8E%E6%A0%87%E5%87%86-html"><span class="nav-number">4.4.</span> <span class="nav-text">wxml 与标准 html</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%A1%B5%E9%9D%A2%E9%97%B4%E4%BC%A0%E9%80%92%E6%95%B0%E6%8D%AE"><span class="nav-number">4.5.</span> <span class="nav-text">页面间传递数据</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%8F%90%E9%AB%98%E5%BA%94%E7%94%A8%E9%80%9F%E5%BA%A6"><span class="nav-number">4.6.</span> <span class="nav-text">提高应用速度</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%94%E3%80%81%E7%BC%96%E7%A8%8B%E7%9B%B8%E5%85%B3"><span class="nav-number">5.</span> <span class="nav-text">五、编程相关</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C"><span class="nav-number">5.1.</span> <span class="nav-text">执行结果</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%BC%E5%90%88%E8%80%83%E5%AF%9F"><span class="nav-number">5.2.</span> <span class="nav-text">综合考察</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%98%E9%87%8F"><span class="nav-number">5.3.</span> <span class="nav-text">变量</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BD%9C%E7%94%A8%E5%9F%9F"><span class="nav-number">5.4.</span> <span class="nav-text">作用域</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#this-%E6%8C%87%E9%92%88"><span class="nav-number">5.5.</span> <span class="nav-text">this 指针</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AF%B9%E8%B1%A1%E5%BA%94%E7%94%A8"><span class="nav-number">5.6.</span> <span class="nav-text">对象应用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BA%8B%E4%BB%B6%E5%BE%AA%E7%8E%AF-x2F-%E5%BC%82%E6%AD%A5"><span class="nav-number">5.7.</span> <span class="nav-text">事件循环&#x2F;异步</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#jsonp-%E5%B0%81%E8%A3%85"><span class="nav-number">5.8.</span> <span class="nav-text">jsonp 封装</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0-sleep"><span class="nav-number">5.9.</span> <span class="nav-text">实现一个函数 sleep</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%9A%84%E7%B1%BB%E5%AE%9E%E7%8E%B0"><span class="nav-number">5.10.</span> <span class="nav-text">消息队列的类实现</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="chuangges" src="" data-original="/images/chuang.png">
  <p class="site-author-name" itemprop="name">chuangges</p>
  <div class="site-description" itemprop="description">chuangge's blog.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">39</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/chuangges" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;chuangges" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://stackoverflow.com/yourname" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;yourname" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-stack-overflow fa-fw"></i>StackOverflow</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://juejin.im/" title="https:&#x2F;&#x2F;juejin.im&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">掘金</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.nowcoder.com/" title="https:&#x2F;&#x2F;www.nowcoder.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">牛客网</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.docschina.org/" title="https:&#x2F;&#x2F;www.docschina.org&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">印记中文</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="http://tool.lu/" title="http:&#x2F;&#x2F;tool.lu&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">在线工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tinypng.com/" title="https:&#x2F;&#x2F;tinypng.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片压缩</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://bigjpg.com/" title="https:&#x2F;&#x2F;bigjpg.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片放大</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tool.chinaz.com/" title="https:&#x2F;&#x2F;tool.chinaz.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">站长工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://learn-anything.xyz/" title="https:&#x2F;&#x2F;learn-anything.xyz&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Learn-Anything</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://stackoverflow.com/" title="https:&#x2F;&#x2F;stackoverflow.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Stack-Overflow</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">chuangge</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
    <span title="站点总字数">1m</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">15:14</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","model":{"jsonPath":"/live2dw/assets/tororo.model.json"},"display":{"position":"left","width":180,"height":360},"mobile":{"show":false},"react":{"opacityDefault":1,"opacityOnHover":1},"log":false,"tagMode":false});</script>
        <style>
            [bg-lazy] {
                background-image: none !important;
                background-color: #eee !important;
            }
        </style>
        <script>
            window.imageLazyLoadSetting = {
                isSPA: false,
                preloadRatio: 1,
                processImages: null,
            };
        </script><script>window.addEventListener("load",function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})});</script><script>!function(e){e.imageLazyLoadSetting.processImages=t;var n=e.imageLazyLoadSetting.isSPA,i=e.imageLazyLoadSetting.preloadRatio||1,r=o();function o(){var t=Array.prototype.slice.call(document.querySelectorAll("img[data-original]")),e=Array.prototype.slice.call(document.querySelectorAll("[bg-lazy]"));return t.concat(e)}function t(){n&&(r=o());for(var t,a=0;a<r.length;a++)0<=(t=(t=r[a]).getBoundingClientRect()).bottom&&0<=t.left&&t.top<=(e.innerHeight*i||document.documentElement.clientHeight*i)&&function(){var t,e,n,i,o=r[a];e=function(){r=r.filter(function(t){return o!==t})},(t=o).hasAttribute("bg-lazy")?(t.removeAttribute("bg-lazy"),e&&e()):(n=new Image,i=t.getAttribute("data-original"),n.onload=function(){t.src=i,t.removeAttribute("data-original"),e&&e()},t.src!==i&&(n.src=i))}()}function a(){clearTimeout(t.tId),t.tId=setTimeout(t,500)}t(),document.addEventListener("scroll",a),e.addEventListener("resize",a),e.addEventListener("orientationchange",a)}(this);</script></body>
</html>
